You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
295 lines
11 KiB
Python
295 lines
11 KiB
Python
from typing import List
|
|
from scripts.faceswaplab_ui.faceswaplab_inpainting_ui import face_inpainting_ui
|
|
from scripts.faceswaplab_swapping.face_checkpoints import get_face_checkpoints
|
|
import gradio as gr
|
|
from modules import shared
|
|
from scripts.faceswaplab_utils.sd_utils import get_sd_option
|
|
|
|
|
|
def faceswap_unit_advanced_options(
|
|
is_img2img: bool, unit_num: int = 1, id_prefix: str = "faceswaplab_"
|
|
) -> List[gr.components.Component]:
|
|
with gr.Accordion(f"Post-Processing & Advanced Mask Options", open=False):
|
|
gr.Markdown(
|
|
"""Post-processing and mask settings for unit faces. Best result : checks all, use LDSR, use Codeformer"""
|
|
)
|
|
with gr.Row():
|
|
face_restorer_name = gr.Radio(
|
|
label="Restore Face",
|
|
choices=["None"] + [x.name() for x in shared.face_restorers],
|
|
value=lambda: get_sd_option(
|
|
"faceswaplab_default_upscaled_swapper_face_restorer",
|
|
"None",
|
|
),
|
|
type="value",
|
|
elem_id=f"{id_prefix}_face{unit_num}_face_restorer",
|
|
)
|
|
with gr.Column():
|
|
face_restorer_visibility = gr.Slider(
|
|
0,
|
|
1,
|
|
value=lambda: get_sd_option(
|
|
"faceswaplab_default_upscaled_swapper_face_restorer_visibility",
|
|
1.0,
|
|
),
|
|
step=0.001,
|
|
label="Restore visibility",
|
|
elem_id=f"{id_prefix}_face{unit_num}_face_restorer_visibility",
|
|
)
|
|
codeformer_weight = gr.Slider(
|
|
0,
|
|
1,
|
|
value=lambda: get_sd_option(
|
|
"faceswaplab_default_upscaled_swapper_face_restorer_weight", 1.0
|
|
),
|
|
step=0.001,
|
|
label="codeformer weight",
|
|
elem_id=f"{id_prefix}_face{unit_num}_face_restorer_weight",
|
|
)
|
|
upscaler_name = gr.Dropdown(
|
|
choices=[upscaler.name for upscaler in shared.sd_upscalers],
|
|
value=lambda: get_sd_option(
|
|
"faceswaplab_default_upscaled_swapper_upscaler", ""
|
|
),
|
|
label="Upscaler",
|
|
elem_id=f"{id_prefix}_face{unit_num}_upscaler",
|
|
)
|
|
|
|
improved_mask = gr.Checkbox(
|
|
lambda: get_sd_option(
|
|
"faceswaplab_default_upscaled_swapper_improved_mask", False
|
|
),
|
|
interactive=True,
|
|
label="Use improved segmented mask (use pastenet to mask only the face)",
|
|
elem_id=f"{id_prefix}_face{unit_num}_improved_mask",
|
|
)
|
|
color_corrections = gr.Checkbox(
|
|
lambda: get_sd_option(
|
|
"faceswaplab_default_upscaled_swapper_fixcolor", False
|
|
),
|
|
interactive=True,
|
|
label="Use color corrections",
|
|
elem_id=f"{id_prefix}_face{unit_num}_color_corrections",
|
|
)
|
|
sharpen_face = gr.Checkbox(
|
|
lambda: get_sd_option(
|
|
"faceswaplab_default_upscaled_swapper_sharpen", False
|
|
),
|
|
interactive=True,
|
|
label="sharpen face",
|
|
elem_id=f"{id_prefix}_face{unit_num}_sharpen_face",
|
|
)
|
|
erosion_factor = gr.Slider(
|
|
0.0,
|
|
10.0,
|
|
lambda: get_sd_option("faceswaplab_default_upscaled_swapper_erosion", 1.0),
|
|
step=0.01,
|
|
label="Upscaled swapper mask erosion factor, 1 = default behaviour.",
|
|
elem_id=f"{id_prefix}_face{unit_num}_erosion_factor",
|
|
)
|
|
|
|
return [
|
|
face_restorer_name,
|
|
face_restorer_visibility,
|
|
codeformer_weight,
|
|
upscaler_name,
|
|
improved_mask,
|
|
color_corrections,
|
|
sharpen_face,
|
|
erosion_factor,
|
|
]
|
|
|
|
|
|
def faceswap_unit_ui(
|
|
is_img2img: bool, unit_num: int = 1, id_prefix: str = "faceswaplab"
|
|
) -> List[gr.components.Component]:
|
|
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)."""
|
|
)
|
|
with gr.Row():
|
|
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",
|
|
)
|
|
gr.Markdown(
|
|
"""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",
|
|
)
|
|
refresh = gr.Button(
|
|
value="↻",
|
|
variant="tool",
|
|
elem_id=f"{id_prefix}_face{unit_num}_refresh_checkpoints",
|
|
)
|
|
|
|
def refresh_fn(selected: str) -> None:
|
|
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",
|
|
)
|
|
blend_faces = gr.Checkbox(
|
|
True,
|
|
placeholder="Blend Faces",
|
|
label="Blend Faces ((Source|Checkpoint)+References = 1)",
|
|
elem_id=f"{id_prefix}_face{unit_num}_blend_faces",
|
|
interactive=True,
|
|
)
|
|
|
|
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",
|
|
)
|
|
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",
|
|
)
|
|
target_faces_index = gr.Textbox(
|
|
value=f"{unit_num-1}",
|
|
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",
|
|
)
|
|
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",
|
|
)
|
|
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",
|
|
)
|
|
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",
|
|
)
|
|
|
|
gr.Markdown(
|
|
"""
|
|
## Advanced Options
|
|
|
|
**Simple :** If you have bad results and don't want to fine-tune here, just enable Codeformer in "Global Post-Processing".
|
|
Otherwise, read the [doc](https://glucauze.github.io/sd-webui-faceswaplab/doc/) to understand following options.
|
|
|
|
"""
|
|
)
|
|
|
|
with gr.Accordion("Similarity", open=False):
|
|
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",
|
|
)
|
|
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",
|
|
)
|
|
|
|
pre_inpainting = face_inpainting_ui(
|
|
name="Pre-Inpainting (Before swapping)",
|
|
id_prefix=f"{id_prefix}_face{unit_num}_preinpainting",
|
|
description="Pre-inpainting sends face to inpainting before swapping",
|
|
)
|
|
|
|
options = faceswap_unit_advanced_options(is_img2img, unit_num, id_prefix)
|
|
|
|
post_inpainting = face_inpainting_ui(
|
|
name="Post-Inpainting (After swapping)",
|
|
id_prefix=f"{id_prefix}_face{unit_num}_postinpainting",
|
|
description="Post-inpainting sends face to inpainting after swapping",
|
|
)
|
|
|
|
gradio_components: List[gr.components.Component] = (
|
|
[
|
|
img,
|
|
face,
|
|
batch_files,
|
|
blend_faces,
|
|
enable,
|
|
same_gender,
|
|
sort_by_size,
|
|
check_similarity,
|
|
compute_similarity,
|
|
min_sim,
|
|
min_ref_sim,
|
|
target_faces_index,
|
|
reference_faces_index,
|
|
swap_in_source,
|
|
swap_in_generated,
|
|
]
|
|
+ pre_inpainting
|
|
+ options
|
|
+ post_inpainting
|
|
)
|
|
|
|
# If changed, you need to change FaceSwapUnitSettings accordingly
|
|
# ORDER of parameters is IMPORTANT. It should match the result of FaceSwapUnitSettings
|
|
return gradio_components
|