add pre-commit hooks configuration
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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,
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user