add gender selection in build

main
Tran Xen 2 years ago
parent c94d2aab4d
commit bba4845dbf

@ -25,21 +25,26 @@ def check_configuration() -> None:
model_path = os.path.join(models_dir, model_name) model_path = os.path.join(models_dir, model_name)
def download(url: str, path: str) -> None: def download(url: str, path: str) -> None:
request = urllib.request.urlopen(url) try:
total = int(request.headers.get("Content-Length", 0)) request = urllib.request.urlopen(url)
with tqdm( total = int(request.headers.get("Content-Length", 0))
total=total, with tqdm(
desc="Downloading inswapper model", total=total,
unit="B", desc="Downloading inswapper model",
unit_scale=True, unit="B",
unit_divisor=1024, unit_scale=True,
) as progress: unit_divisor=1024,
urllib.request.urlretrieve( ) as progress:
url, urllib.request.urlretrieve(
path, url,
reporthook=lambda count, block_size, total_size: progress.update( path,
block_size reporthook=lambda count, block_size, total_size: progress.update(
), block_size
),
)
except:
logger.error(
"Failed to download inswapper_128.onnx model, please download it manually and put it in the (<sdwebui>/models/faceswaplab/inswapper_128.onnx) directory"
) )
os.makedirs(models_dir, exist_ok=True) os.makedirs(models_dir, exist_ok=True)

@ -39,6 +39,7 @@ def sanitize_name(name: str) -> str:
def build_face_checkpoint_and_save( def build_face_checkpoint_and_save(
images: List[PILImage], images: List[PILImage],
name: str, name: str,
gender: Gender = Gender.AUTO,
overwrite: bool = False, overwrite: bool = False,
path: Optional[str] = None, path: Optional[str] = None,
) -> Optional[PILImage]: ) -> Optional[PILImage]:
@ -64,7 +65,7 @@ def build_face_checkpoint_and_save(
logger.error("No source faces found") logger.error("No source faces found")
return None return None
blended_face: Optional[Face] = swapper.blend_faces(faces) blended_face: Optional[Face] = swapper.blend_faces(faces, gender=gender)
preview_path = os.path.join( preview_path = os.path.join(
scripts.basedir(), "extensions", "sd-webui-faceswaplab", "references" scripts.basedir(), "extensions", "sd-webui-faceswaplab", "references"
) )

@ -33,7 +33,7 @@ from scripts.faceswaplab_postprocessing.postprocessing_options import (
PostProcessingOptions, PostProcessingOptions,
) )
from scripts.faceswaplab_utils.models_utils import get_current_swap_model from scripts.faceswaplab_utils.models_utils import get_current_swap_model
from scripts.faceswaplab_utils.typing import CV2ImgU8, PILImage, Face from scripts.faceswaplab_utils.typing import CV2ImgU8, Gender, PILImage, Face
from scripts.faceswaplab_inpainting.i2i_pp import img2img_diffusion from scripts.faceswaplab_inpainting.i2i_pp import img2img_diffusion
from modules import shared from modules import shared
import onnxruntime import onnxruntime
@ -559,7 +559,7 @@ def get_faces_from_img_files(images: List[PILImage]) -> List[Face]:
return faces return faces
def blend_faces(faces: List[Face]) -> Optional[Face]: def blend_faces(faces: List[Face], gender: Gender = Gender.AUTO) -> Optional[Face]:
""" """
Blends the embeddings of multiple faces into a single face. Blends the embeddings of multiple faces into a single face.
@ -587,10 +587,19 @@ def blend_faces(faces: List[Face]) -> Optional[Face]:
# Compute the mean of all embeddings # Compute the mean of all embeddings
blended_embedding = np.mean(embeddings, axis=0) blended_embedding = np.mean(embeddings, axis=0)
if gender == Gender.AUTO:
int_gender: int = faces[0].gender # type: ignore
else:
int_gender: int = gender.value
assert -1 < int_gender < 2, "wrong gender"
logger.info("Int Gender : %s", int_gender)
# Create a new Face object using the properties of the first face in the list # Create a new Face object using the properties of the first face in the list
# Assign the blended embedding to the blended Face object # Assign the blended embedding to the blended Face object
blended = ISFace( blended = ISFace(
embedding=blended_embedding, gender=faces[0].gender, age=faces[0].age embedding=blended_embedding, gender=int_gender, age=faces[0].age
) )
return blended return blended

@ -137,7 +137,7 @@ def analyse_faces(image: PILImage, det_threshold: float = 0.5) -> Optional[str]:
def build_face_checkpoint_and_save( def build_face_checkpoint_and_save(
batch_files: List[gr.File], name: str, overwrite: bool batch_files: List[gr.File], name: str, str_gender: str, overwrite: bool
) -> PILImage: ) -> PILImage:
""" """
Builds a face checkpoint using the provided image files, performs face swapping, Builds a face checkpoint using the provided image files, performs face swapping,
@ -156,10 +156,13 @@ def build_face_checkpoint_and_save(
if not batch_files: if not batch_files:
logger.error("No face found") logger.error("No face found")
return None # type: ignore (Optional not really supported by old gradio) return None # type: ignore (Optional not really supported by old gradio)
gender = getattr(Gender, str_gender)
logger.info("Choosen gender : %s", gender)
images: list[PILImage] = [Image.open(file.name) for file in batch_files] # type: ignore images: list[PILImage] = [Image.open(file.name) for file in batch_files] # type: ignore
preview_image: PILImage | None = ( preview_image: PILImage | None = (
face_checkpoints.build_face_checkpoint_and_save( face_checkpoints.build_face_checkpoint_and_save(
images=images, name=name, overwrite=overwrite images=images, name=name, overwrite=overwrite, gender=gender
) )
) )
except Exception as e: except Exception as e:
@ -266,6 +269,13 @@ def tools_ui() -> None:
label="Name of the character", label="Name of the character",
elem_id="faceswaplab_build_character_name", elem_id="faceswaplab_build_character_name",
) )
build_gender = gr.Dropdown(
value=Gender.AUTO.name,
choices=[e.name for e in Gender],
placeholder="Gender of the character",
label="Gender of the character",
elem_id="faceswaplab_build_character_gender",
)
build_overwrite = gr.Checkbox( build_overwrite = gr.Checkbox(
False, False,
placeholder="overwrite", placeholder="overwrite",
@ -387,7 +397,7 @@ def tools_ui() -> None:
compare_btn.click(compare, inputs=[img1, img2], outputs=[compare_result_text]) compare_btn.click(compare, inputs=[img1, img2], outputs=[compare_result_text])
generate_checkpoint_btn.click( generate_checkpoint_btn.click(
build_face_checkpoint_and_save, build_face_checkpoint_and_save,
inputs=[build_batch_files, build_name, build_overwrite], inputs=[build_batch_files, build_name, build_gender, build_overwrite],
outputs=[preview], outputs=[preview],
) )
extract_btn.click( extract_btn.click(

@ -73,14 +73,14 @@ def get_current_swap_model() -> str:
model = models[0] if len(models) else None model = models[0] if len(models) else None
logger.info("Try to use model : %s", model) logger.info("Try to use model : %s", model)
try: try:
if not os.path.isfile(model): # type: ignore if not model or not os.path.isfile(model): # type: ignore
logger.error("The model %s cannot be found or loaded", model) logger.error("The model %s cannot be found or loaded", model)
raise FileNotFoundError( raise FileNotFoundError(
"No faceswap model found. Please add it to the faceswaplab directory." "No faceswap model found. Please add it to the faceswaplab directory. Ensure the model is in the proper directory (<sdwebui>/models/faceswaplab/inswapper_128.onnx)"
) )
except: except:
raise FileNotFoundError( raise FileNotFoundError(
"Was not able to check model, please ensure the model is in the proper directory" "No faceswap model found. Please add it to the faceswaplab directory. Ensure the model is in the proper directory (<sdwebui>/models/faceswaplab/inswapper_128.onnx)"
) )
assert model is not None assert model is not None

@ -3,8 +3,15 @@ from numpy import uint8
from insightface.app.common import Face as IFace from insightface.app.common import Face as IFace
from PIL import Image from PIL import Image
import numpy as np import numpy as np
from enum import Enum
PILImage = Image.Image PILImage = Image.Image
CV2ImgU8 = np.ndarray[int, np.dtype[uint8]] CV2ImgU8 = np.ndarray[int, np.dtype[uint8]]
Face = IFace Face = IFace
BoxCoords = Tuple[int, int, int, int] BoxCoords = Tuple[int, int, int, int]
class Gender(Enum):
AUTO = -1
FEMALE = 0
MALE = 1

Loading…
Cancel
Save