12 Commits

Author SHA1 Message Date
Tran Xen 42d1c75b68 Merge pull request #96 from glucauze/v1.2.7
v1.2.7 

    remove dill
    add warnings in model install and checking
    add gender selection in build
2023-09-10 16:06:47 +02:00
Tran Xen bba4845dbf add gender selection in build 2023-09-09 16:25:06 +02:00
Tran Xen c94d2aab4d v1.2.7 2023-09-09 10:51:36 +02:00
Tran Xen 0d0242e0ac Merge pull request #83 from glucauze/v1.2.6
fix inpainting in auto dev version
2023-08-31 14:46:25 +02:00
Tran Xen 806086b533 Merge pull request #71 from glucauze/v1.2.5
add seed selection
2023-08-25 10:48:03 +02:00
Tran Xen 9977168136 Merge pull request #68 from glucauze/v1.2.4
V1.2.4 :

Fix default settings by marking only managed field as do_not_save.

See the discussion here : #62
2023-08-24 19:35:23 +02:00
Tran Xen c4badb7894 Merge pull request #66 from glucauze/v1.2.3
fix install
2023-08-24 10:02:25 +02:00
Tran Xen a6ccd6fd40 Merge pull request #63 from glucauze/v1.2.3
change model link
2023-08-23 18:00:51 +02:00
Tran Xen abdcf4a494 Merge pull request #61 from glucauze/v1.2.3
speed up ui, BREAKING : see changelog
2023-08-23 14:21:52 +02:00
Tran Xen 32eeed8bd7 Merge pull request #57 from glucauze/v1.2.2a
change model url
2023-08-21 22:23:54 +02:00
Tran Xen d1a82d520d Merge pull request #53 from glucauze/v1.2.2a
remove javascript since it's not really relevant to the extension
2023-08-17 23:51:32 +02:00
Tran Xen 272dca83b8 Merge pull request #49 from glucauze/v1.2.2a
fix bug in improved mask
2023-08-17 12:14:20 +02:00
10 changed files with 74 additions and 40 deletions
+8 -2
View File
@@ -62,5 +62,11 @@ def check_install() -> None:
import timeit import timeit
check_time = timeit.timeit(check_install, number=1) try:
print(check_time) check_time = timeit.timeit(check_install, number=1)
print(check_time)
except Exception as e:
print("FaceswapLab install failed", e)
print(
"You can try to install dependencies manually by activating venv and installing requirements.txt or requirements-gpu.txt"
)
-1
View File
@@ -1,5 +1,4 @@
cython cython
dill
ifnude ifnude
insightface==0.7.3 insightface==0.7.3
onnx>=1.14.0 onnx>=1.14.0
-1
View File
@@ -1,6 +1,5 @@
protobuf>=3.20.2 protobuf>=3.20.2
cython cython
dill
ifnude ifnude
insightface==0.7.3 insightface==0.7.3
onnx>=1.14.0 onnx>=1.14.0
+20 -15
View File
@@ -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)
+1 -1
View File
@@ -16,7 +16,7 @@ REFERENCE_PATH = os.path.join(
) )
# Defining the version flag for the application # Defining the version flag for the application
VERSION_FLAG: str = "v1.2.5" VERSION_FLAG: str = "v1.2.7"
# Defining the path for 'sd-webui-faceswaplab' inside the 'extensions' directory # Defining the path for 'sd-webui-faceswaplab' inside the 'extensions' directory
EXTENSION_PATH = os.path.join("extensions", "sd-webui-faceswaplab") EXTENSION_PATH = os.path.join("extensions", "sd-webui-faceswaplab")
@@ -14,7 +14,6 @@ from scripts.faceswaplab_utils import imgutils
from scripts.faceswaplab_utils.models_utils import get_swap_models from scripts.faceswaplab_utils.models_utils import get_swap_models
import traceback import traceback
import dill as pickle # will be removed in future versions
from scripts.faceswaplab_swapping import swapper from scripts.faceswaplab_swapping import swapper
from pprint import pformat from pprint import pformat
import re import re
@@ -40,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]:
@@ -65,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"
) )
@@ -174,20 +174,13 @@ def load_face(name: str) -> Optional[Face]:
if filename.endswith(".pkl"): if filename.endswith(".pkl"):
logger.warning( logger.warning(
"Pkl files for faces are deprecated to enhance safety, they will be unsupported in future versions." "Pkl files for faces are deprecated to enhance safety, you need to convert them"
) )
logger.warning("The file will be converted to .safetensors") logger.warning("The file will be converted to .safetensors")
logger.warning( logger.warning(
"You can also use this script https://gist.github.com/glucauze/4a3c458541f2278ad801f6625e5b9d3d" "You can also use this script https://gist.github.com/glucauze/4a3c458541f2278ad801f6625e5b9d3d"
) )
with open(filename, "rb") as file: return None
logger.info("Load pkl")
face = Face(pickle.load(file))
logger.warning(
"Convert to safetensors, you can remove the pkl version once you have ensured that the safetensor is working"
)
save_face(face, filename.replace(".pkl", ".safetensors"))
return face
elif filename.endswith(".safetensors"): elif filename.endswith(".safetensors"):
face = {} face = {}
+12 -3
View File
@@ -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
+13 -3
View File
@@ -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(
+9 -3
View File
@@ -72,10 +72,16 @@ def get_current_swap_model() -> str:
models = get_swap_models() models = get_swap_models()
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)
if not os.path.isfile(model): # type: ignore try:
logger.error("The model %s cannot be found or loaded", model) if not model or not os.path.isfile(model): # type: ignore
logger.error("The model %s cannot be found or loaded", model)
raise FileNotFoundError(
"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:
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)"
) )
assert model is not None assert model is not None
return model return model
+7
View File
@@ -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