1
0
Fork 0
mirror of https://github.com/deepfakes/faceswap synced 2025-06-07 10:43:27 -04:00

Update all Keras Imports to be conditional (#1214)

* Remove custom keras importer

* first round keras imports fix

* launcher.py: Remove KerasFinder references

* 2nd round keras imports update (lib and extract)

* 3rd round keras imports update (train)

* remove KerasFinder from tests

* 4th round keras imports update (tests)
This commit is contained in:
torzdf 2022-05-03 20:18:39 +01:00 committed by GitHub
parent b1e0e6ea82
commit aa39234538
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
35 changed files with 398 additions and 333 deletions

View file

@ -9,7 +9,7 @@ from importlib import import_module
from lib.gpu_stats import set_exclude_devices, GPUStats
from lib.logger import crash_log, log_setup
from lib.utils import (FaceswapError, get_backend, get_tf_version, KerasFinder, safe_shutdown,
from lib.utils import (FaceswapError, get_backend, get_tf_version, safe_shutdown,
set_backend, set_system_verbosity)
logger = logging.getLogger(__name__) # pylint: disable=invalid-name
@ -206,8 +206,6 @@ class ScriptExecutor(): # pylint:disable=too-few-public-methods
Set Faceswap backend to CPU if all GPUs have been deselected.
Add the Keras import interception code.
Parameters
----------
arguments: :class:`argparse.Namespace`
@ -234,9 +232,6 @@ class ScriptExecutor(): # pylint:disable=too-few-public-methods
set_backend("cpu")
logger.info(msg)
# Add Keras finder to the meta_path list as the first item
sys.meta_path.insert(0, KerasFinder())
logger.debug("Executing: %s. PID: %s", self._command, os.getpid())
if get_backend() == "amd":

View file

@ -7,10 +7,17 @@ import inspect
import numpy as np
import tensorflow as tf
from keras import backend as K
from keras import initializers
from lib.utils import get_backend, get_keras_custom_objects as get_custom_objects
from lib.utils import get_backend
if get_backend() == "amd":
from keras.utils import get_custom_objects # pylint:disable=no-name-in-module
from keras import backend as K
from keras import initializers
else:
# Ignore linting errors from Tensorflow's thoroughly broken import system
from tensorflow.keras.utils import get_custom_objects # noqa pylint:disable=no-name-in-module,import-error
from tensorflow.keras import initializers, backend as K # noqa pylint:disable=no-name-in-module,import-error
logger = logging.getLogger(__name__) # pylint: disable=invalid-name

View file

@ -7,16 +7,19 @@ import sys
import inspect
import tensorflow as tf
import keras.backend as K
from keras.layers import InputSpec, Layer
from lib.utils import get_backend, get_keras_custom_objects as get_custom_objects
from lib.utils import get_backend
if get_backend() == "amd":
from lib.plaidml_utils import pad
from keras.utils import conv_utils # pylint:disable=ungrouped-imports
from keras.utils import get_custom_objects, conv_utils # pylint:disable=no-name-in-module
import keras.backend as K
from keras.layers import InputSpec, Layer
else:
# Ignore linting errors from Tensorflow's thoroughly broken import system
from tensorflow.keras.utils import get_custom_objects # noqa pylint:disable=no-name-in-module,import-error
from tensorflow.keras import backend as K # pylint:disable=import-error
from tensorflow.keras.layers import InputSpec, Layer # noqa pylint:disable=no-name-in-module,import-error
from tensorflow import pad
from tensorflow.python.keras.utils import conv_utils # pylint:disable=no-name-in-module

View file

@ -7,11 +7,12 @@ import logging
import numpy as np
import tensorflow as tf
from tensorflow.python.keras.engine import compile_utils # pylint:disable=no-name-in-module
from keras import backend as K
# Ignore linting errors from Tensorflow's thoroughly broken import system
from tensorflow.python.keras.engine import compile_utils # noqa pylint:disable=no-name-in-module,import-error
from tensorflow.keras import backend as K # pylint:disable=import-error
logger = logging.getLogger(__name__) # pylint:disable=invalid-name
logger = logging.getLogger(__name__)
class DSSIMObjective(tf.keras.losses.Loss): # pylint:disable=too-few-public-methods

View file

@ -3,20 +3,31 @@
import logging
from keras.layers import (Activation, Add, BatchNormalization, Concatenate, Conv2D as KConv2D,
Conv2DTranspose, DepthwiseConv2D as KDepthwiseConv2d, LeakyReLU, PReLU,
SeparableConv2D, UpSampling2D)
from keras.initializers import he_uniform, VarianceScaling
from lib.utils import get_backend
from .initializers import ICNR, ConvolutionAware
from .layers import PixelShuffler, ReflectionPadding2D, Swish, KResizeImages
from .normalization import InstanceNormalization
if get_backend() == "amd":
from keras.layers import (
Activation, Add, BatchNormalization, Concatenate, Conv2D as KConv2D, Conv2DTranspose,
DepthwiseConv2D as KDepthwiseConv2d, LeakyReLU, PReLU, SeparableConv2D, UpSampling2D)
from keras.initializers import he_uniform, VarianceScaling # pylint:disable=no-name-in-module
else:
# Ignore linting errors from Tensorflow's thoroughly broken import system
from tensorflow.keras.layers import ( # noqa pylint:disable=no-name-in-module,import-error
Activation, Add, BatchNormalization, Concatenate, Conv2D as KConv2D, Conv2DTranspose,
DepthwiseConv2D as KDepthwiseConv2d, LeakyReLU, PReLU, SeparableConv2D, UpSampling2D)
from tensorflow.keras.initializers import he_uniform, VarianceScaling # noqa pylint:disable=no-name-in-module,import-error
logger = logging.getLogger(__name__) # pylint: disable=invalid-name
_CONFIG = dict()
_NAMES = dict()
_CONFIG = {}
_NAMES = {}
def set_config(configuration):
@ -52,9 +63,9 @@ def _get_name(name):
str
The unique name for this layer
"""
global _NAMES # pylint:disable=global-statement
global _NAMES # pylint:disable=global-statement,global-variable-not-assigned
_NAMES[name] = _NAMES.setdefault(name, -1) + 1
name = "{}_{}".format(name, _NAMES[name])
name = f"{name}_{_NAMES[name]}"
logger.debug("Generating block name: %s", name)
return name
@ -112,7 +123,7 @@ class Conv2D(KConv2D): # pylint:disable=too-few-public-methods
def __init__(self, *args, padding="same", check_icnr_init=False, **kwargs):
if kwargs.get("name", None) is None:
filters = kwargs["filters"] if "filters" in kwargs else args[0]
kwargs["name"] = _get_name("conv2d_{}".format(filters))
kwargs["name"] = _get_name(f"conv2d_{filters}")
initializer = _get_default_initializer(kwargs.pop("kernel_initializer", None))
if check_icnr_init and _CONFIG["icnr_init"]:
initializer = ICNR(initializer=initializer)
@ -179,7 +190,7 @@ class Conv2DOutput(): # pylint:disable=too-few-public-methods
"""
def __init__(self, filters, kernel_size, activation="sigmoid", padding="same", **kwargs):
self._name = kwargs.pop("name") if "name" in kwargs else _get_name(
"conv_output_{}".format(filters))
f"conv_output_{filters}")
self._filters = filters
self._kernel_size = kernel_size
self._activation = activation
@ -202,7 +213,7 @@ class Conv2DOutput(): # pylint:disable=too-few-public-methods
var_x = Conv2D(self._filters,
self._kernel_size,
padding=self._padding,
name="{}_conv2d".format(self._name),
name=f"{self._name}_conv2d",
**self._kwargs)(inputs)
var_x = Activation(self._activation, dtype="float32", name=self._name)(var_x)
return var_x
@ -256,8 +267,7 @@ class Conv2DBlock(): # pylint:disable=too-few-public-methods
activation="leakyrelu",
use_depthwise=False,
**kwargs):
self._name = kwargs.pop("name") if "name" in kwargs else _get_name(
"conv_{}".format(filters))
self._name = kwargs.pop("name") if "name" in kwargs else _get_name(f"conv_{filters}")
logger.debug("name: %s, filters: %s, kernel_size: %s, strides: %s, padding: %s, "
"normalization: %s, activation: %s, use_depthwise: %s, kwargs: %s)",
@ -299,26 +309,26 @@ class Conv2DBlock(): # pylint:disable=too-few-public-methods
if self._use_reflect_padding:
inputs = ReflectionPadding2D(stride=self._strides,
kernel_size=self._args[-1],
name="{}_reflectionpadding2d".format(self._name))(inputs)
name=f"{self._name}_reflectionpadding2d")(inputs)
conv = DepthwiseConv2D if self._use_depthwise else Conv2D
var_x = conv(*self._args,
strides=self._strides,
padding=self._padding,
name="{}_{}conv2d".format(self._name, "dw" if self._use_depthwise else ""),
name=f"{self._name}_{'dw' if self._use_depthwise else ''}conv2d",
**self._kwargs)(inputs)
# normalization
if self._normalization == "instance":
var_x = InstanceNormalization(name="{}_instancenorm".format(self._name))(var_x)
var_x = InstanceNormalization(name=f"{self._name}_instancenorm")(var_x)
if self._normalization == "batch":
var_x = BatchNormalization(axis=3, name="{}_batchnorm".format(self._name))(var_x)
var_x = BatchNormalization(axis=3, name=f"{self._name}_batchnorm")(var_x)
# activation
if self._activation == "leakyrelu":
var_x = LeakyReLU(0.1, name="{}_leakyrelu".format(self._name))(var_x)
var_x = LeakyReLU(0.1, name=f"{self._name}_leakyrelu")(var_x)
if self._activation == "swish":
var_x = Swish(name="{}_swish".format(self._name))(var_x)
var_x = Swish(name=f"{self._name}_swish")(var_x)
if self._activation == "prelu":
var_x = PReLU(name="{}_prelu".format(self._name))(var_x)
var_x = PReLU(name=f"{self._name}_prelu")(var_x)
return var_x
@ -344,7 +354,7 @@ class SeparableConv2DBlock(): # pylint:disable=too-few-public-methods
Convolutional 2D layer
"""
def __init__(self, filters, kernel_size=5, strides=2, **kwargs):
self._name = _get_name("separableconv2d_{}".format(filters))
self._name = _get_name(f"separableconv2d_{filters}")
logger.debug("name: %s, filters: %s, kernel_size: %s, strides: %s, kwargs: %s)",
self._name, filters, kernel_size, strides, kwargs)
@ -373,9 +383,9 @@ class SeparableConv2DBlock(): # pylint:disable=too-few-public-methods
kernel_size=self._kernel_size,
strides=self._strides,
padding="same",
name="{}_seperableconv2d".format(self._name),
name=f"{self._name}_seperableconv2d",
**self._kwargs)(inputs)
var_x = Activation("relu", name="{}_relu".format(self._name))(var_x)
var_x = Activation("relu", name=f"{self._name}_relu")(var_x)
return var_x
@ -420,7 +430,7 @@ class UpscaleBlock(): # pylint:disable=too-few-public-methods
normalization=None,
activation="leakyrelu",
**kwargs):
self._name = _get_name("upscale_{}".format(filters))
self._name = _get_name(f"upscale_{filters}")
logger.debug("name: %s. filters: %s, kernel_size: %s, padding: %s, scale_factor: %s, "
"normalization: %s, activation: %s, kwargs: %s)",
self._name, filters, kernel_size, padding, scale_factor, normalization,
@ -453,10 +463,10 @@ class UpscaleBlock(): # pylint:disable=too-few-public-methods
padding=self._padding,
normalization=self._normalization,
activation=self._activation,
name="{}_conv2d".format(self._name),
name=f"{self._name}_conv2d",
check_icnr_init=_CONFIG["icnr_init"],
**self._kwargs)(inputs)
var_x = PixelShuffler(name="{}_pixelshuffler".format(self._name),
var_x = PixelShuffler(name=f"{self._name}_pixelshuffler",
size=self._scale_factor)(var_x)
return var_x
@ -501,7 +511,7 @@ class Upscale2xBlock(): # pylint:disable=too-few-public-methods
"""
def __init__(self, filters, kernel_size=3, padding="same", activation="leakyrelu",
interpolation="bilinear", sr_ratio=0.5, scale_factor=2, fast=False, **kwargs):
self._name = _get_name("upscale2x_{}_{}".format(filters, "fast" if fast else "hyb"))
self._name = _get_name(f"upscale2x_{filters}_{'fast' if fast else 'hyb'}")
self._fast = fast
self._filters = filters if self._fast else filters - int(filters * sr_ratio)
@ -536,11 +546,11 @@ class Upscale2xBlock(): # pylint:disable=too-few-public-methods
if self._fast or (not self._fast and self._filters > 0):
var_x2 = Conv2D(self._filters, 3,
padding=self._padding,
name="{}_conv2d".format(self._name),
name=f"{self._name}_conv2d",
**self._kwargs)(var_x)
var_x2 = UpSampling2D(size=(self._scale_factor, self._scale_factor),
interpolation=self._interpolation,
name="{}_upsampling2D".format(self._name))(var_x2)
name=f"{self._name}_upsampling2D")(var_x2)
if self._fast:
var_x1 = UpscaleBlock(self._filters,
kernel_size=self._kernel_size,
@ -550,7 +560,7 @@ class Upscale2xBlock(): # pylint:disable=too-few-public-methods
**self._kwargs)(var_x)
var_x = Add()([var_x2, var_x1])
else:
var_x = Concatenate(name="{}_concatenate".format(self._name))([var_x_sr, var_x2])
var_x = Concatenate(name=f"{self._name}_concatenate")([var_x_sr, var_x2])
else:
var_x = var_x_sr
return var_x
@ -587,7 +597,7 @@ class UpscaleResizeImagesBlock(): # pylint:disable=too-few-public-methods
"""
def __init__(self, filters, kernel_size=3, padding="same", activation="leakyrelu",
scale_factor=2, interpolation="bilinear"):
self._name = _get_name("upscale_ri_{}".format(filters))
self._name = _get_name(f"upscale_ri_{filters}")
self._interpolation = interpolation
self._size = scale_factor
self._filters = filters
@ -612,23 +622,23 @@ class UpscaleResizeImagesBlock(): # pylint:disable=too-few-public-methods
var_x_sr = KResizeImages(size=self._size,
interpolation=self._interpolation,
name="{}_resize".format(self._name))(var_x)
name=f"{self._name}_resize")(var_x)
var_x_sr = Conv2D(self._filters, self._kernel_size,
strides=1,
padding=self._padding,
name="{}_conv".format(self._name))(var_x_sr)
name=f"{self._name}_conv")(var_x_sr)
var_x_us = Conv2DTranspose(self._filters, 3,
strides=2,
padding=self._padding,
name="{}_convtrans".format(self._name))(var_x)
name=f"{self._name}_convtrans")(var_x)
var_x = Add()([var_x_sr, var_x_us])
if self._activation == "leakyrelu":
var_x = LeakyReLU(0.2, name="{}_leakyrelu".format(self._name))(var_x)
var_x = LeakyReLU(0.2, name=f"{self._name}_leakyrelu")(var_x)
if self._activation == "swish":
var_x = Swish(name="{}_swish".format(self._name))(var_x)
var_x = Swish(name=f"{self._name}_swish")(var_x)
if self._activation == "prelu":
var_x = PReLU(name="{}_prelu".format(self._name))(var_x)
var_x = PReLU(name=f"{self._name}_prelu")(var_x)
return var_x
@ -656,7 +666,7 @@ class ResidualBlock(): # pylint:disable=too-few-public-methods
The output tensor from the Upscale layer
"""
def __init__(self, filters, kernel_size=3, padding="same", **kwargs):
self._name = _get_name("residual_{}".format(filters))
self._name = _get_name(f"residual_{filters}")
logger.debug("name: %s, filters: %s, kernel_size: %s, padding: %s, kwargs: %s)",
self._name, filters, kernel_size, padding, kwargs)
self._use_reflect_padding = _CONFIG["reflect_padding"]
@ -683,17 +693,17 @@ class ResidualBlock(): # pylint:disable=too-few-public-methods
if self._use_reflect_padding:
var_x = ReflectionPadding2D(stride=1,
kernel_size=self._kernel_size,
name="{}_reflectionpadding2d_0".format(self._name))(var_x)
name=f"{self._name}_reflectionpadding2d_0")(var_x)
var_x = Conv2D(self._filters,
kernel_size=self._kernel_size,
padding=self._padding,
name="{}_conv2d_0".format(self._name),
name=f"{self._name}_conv2d_0",
**self._kwargs)(var_x)
var_x = LeakyReLU(alpha=0.2, name="{}_leakyrelu_1".format(self._name))(var_x)
var_x = LeakyReLU(alpha=0.2, name=f"{self._name}_leakyrelu_1")(var_x)
if self._use_reflect_padding:
var_x = ReflectionPadding2D(stride=1,
kernel_size=self._kernel_size,
name="{}_reflectionpadding2d_1".format(self._name))(var_x)
name=f"{self._name}_reflectionpadding2d_1")(var_x)
kwargs = {key: val for key, val in self._kwargs.items() if key != "kernel_initializer"}
if not _CONFIG["conv_aware_init"]:
@ -703,9 +713,9 @@ class ResidualBlock(): # pylint:disable=too-few-public-methods
var_x = Conv2D(self._filters,
kernel_size=self._kernel_size,
padding=self._padding,
name="{}_conv2d_1".format(self._name),
name=f"{self._name}_conv2d_1",
**kwargs)(var_x)
var_x = Add()([var_x, inputs])
var_x = LeakyReLU(alpha=0.2, name="{}_leakyrelu_3".format(self._name))(var_x)
var_x = LeakyReLU(alpha=0.2, name=f"{self._name}_leakyrelu_3")(var_x)
return var_x

View file

@ -4,19 +4,19 @@
import sys
import inspect
from keras.layers import Layer, InputSpec
from keras import initializers, regularizers, constraints
from keras import backend as K
from lib.utils import get_backend, get_keras_custom_objects as get_custom_objects
from lib.utils import get_backend
if get_backend() == "amd":
from keras.backend \
import normalize_data_format # pylint:disable=ungrouped-imports,no-name-in-module
from keras.utils import get_custom_objects # pylint:disable=no-name-in-module
from keras.layers import Layer, InputSpec
from keras import initializers, regularizers, constraints, backend as K
from keras.backend import normalize_data_format # pylint:disable=no-name-in-module
else:
# pylint:disable=no-name-in-module
from tensorflow.python.keras.utils.conv_utils \
import normalize_data_format # pylint:disable=no-name-in-module
# Ignore linting errors from Tensorflow's thoroughly broken import system
from tensorflow.keras.utils import get_custom_objects # noqa pylint:disable=no-name-in-module,import-error
from tensorflow.keras.layers import Layer, InputSpec # noqa pylint:disable=no-name-in-module,import-error
from tensorflow.keras import initializers, regularizers, constraints, backend as K # noqa pylint:disable=no-name-in-module,import-error
from tensorflow.python.keras.utils.conv_utils import normalize_data_format # noqa pylint:disable=no-name-in-module
class InstanceNormalization(Layer):

View file

@ -4,14 +4,10 @@ import inspect
import sys
import tensorflow as tf
import tensorflow.keras.backend as K # pylint:disable=no-name-in-module,import-error
# tf.keras has a LayerNormaliztion implementation
# pylint:disable=unused-import
from tensorflow.keras.layers import ( # noqa pylint:disable=no-name-in-module,import-error
Layer,
LayerNormalization)
from lib.utils import get_keras_custom_objects as get_custom_objects
# Ignore linting errors from Tensorflow's thoroughly broken import system
from tensorflow.keras import backend as K # pylint:disable=import-error
from tensorflow.keras.layers import Layer, LayerNormalization # noqa pylint:disable=no-name-in-module,unused-import,import-error
from tensorflow.keras.utils import get_custom_objects # noqa pylint:disable=no-name-in-module,import-error
class RMSNormalization(Layer):

View file

@ -8,10 +8,10 @@ import inspect
import sys
import tensorflow as tf
from tensorflow.keras.optimizers import ( # noqa pylint:disable=no-name-in-module,unused-import,import-error
Adam, Nadam, RMSprop)
from lib.utils import get_keras_custom_objects as get_custom_objects
# Ignore linting errors from Tensorflow's thoroughly broken import system
from tensorflow.keras.optimizers import (Adam, Nadam, RMSprop) # noqa pylint:disable=no-name-in-module,unused-import,import-error
from tensorflow.keras.utils import get_custom_objects # noqa pylint:disable=no-name-in-module,import-error
class AdaBelief(tf.keras.optimizers.Optimizer):

View file

@ -5,12 +5,17 @@ import logging
import numpy as np
import tensorflow as tf
# pylint:disable=no-name-in-module,import-error
from keras.layers import Activation
from keras.models import load_model as k_load_model, Model
from lib.utils import get_backend
if get_backend() == "amd":
from keras.layers import Activation
from keras.models import load_model as k_load_model, Model
else:
# Ignore linting errors from Tensorflow's thoroughly broken import system
from tensorflow.keras.layers import Activation # noqa pylint:disable=no-name-in-module,import-error
from tensorflow.keras.models import load_model as k_load_model, Model # noqa pylint:disable=no-name-in-module,import-error
logger = logging.getLogger(__name__) # pylint:disable=invalid-name
@ -54,7 +59,7 @@ class KSession():
self._backend = get_backend()
self._set_session(allow_growth, exclude_gpus)
self._model_path = model_path
self._model_kwargs = dict() if not model_kwargs else model_kwargs
self._model_kwargs = {} if not model_kwargs else model_kwargs
self._model = None
logger.trace("Initialized: %s", self.__class__.__name__,)
@ -92,7 +97,7 @@ class KSession():
feed = [feed]
items = feed[0].shape[0]
done_items = 0
results = list()
results = []
while done_items < items:
if batch_size < 4: # Not much difference in BS < 4
batch_size = 1

View file

@ -1,7 +1,6 @@
#!/usr/bin python3
""" Utilities available across all scripts """
import importlib
import json
import logging
import os
@ -147,17 +146,6 @@ def get_tf_version():
return _TF_VERS
def get_keras_custom_objects():
""" Wrapper to obtain keras.utils.get_custom_objects from correct location depending on
backend used and tensorflow version. """
# pylint:disable=no-name-in-module,import-outside-toplevel
if get_backend() == "amd" or get_tf_version() < 2.8:
from keras.utils import get_custom_objects
else:
from keras.utils.generic_utils import get_custom_objects
return get_custom_objects()
def get_folder(path, make_folder=True):
""" Return a path to a folder, creating it if it doesn't exist
@ -609,73 +597,3 @@ class GetModel(): # pylint:disable=too-few-public-methods
out_file.write(buffer)
zip_file.close()
pbar.close()
class KerasFinder(importlib.abc.MetaPathFinder):
""" Importlib Abstract Base Class for intercepting the import of Keras and returning either
Keras (AMD backend) or tensorflow.keras (any other backend).
The Importlib documentation is sparse at best, and real world examples are pretty much
non-existent. Coupled with this, the import ``tensorflow.keras`` does not resolve so we need
to split out to the actual location of Keras within ``tensorflow_core``. This method works, but
it relies on hard coded paths, and is likely to not be the most robust.
A custom loader is not used, as we can use the standard loader once we have returned the
correct spec.
"""
def __init__(self):
self._logger = logging.getLogger(__name__)
self._backend = get_backend()
self._tf_keras_locations = [["tensorflow_core", "python", "keras", "api", "_v2"],
["tensorflow", "python", "keras", "api", "_v2"]]
def find_spec(self, fullname, path, target=None): # pylint:disable=unused-argument
""" Obtain the spec for either keras or tensorflow.keras depending on the backend in use.
If keras is not passed in as part of the :attr:`fullname` or the path is not ``None``
(i.e this is a dependency import) then this returns ``None`` to use the standard import
library.
Parameters
----------
fullname: str
The absolute name of the module to be imported
path: str
The search path for the module
target: module object, optional
Inherited from parent but unused
Returns
-------
:class:`importlib.ModuleSpec`
The spec for the Keras module to be imported
"""
prefix = fullname.split(".")[0]
suffix = fullname.split(".")[-1]
if prefix != "keras" or path is not None:
return None
self._logger.debug("Importing '%s' as keras for backend: '%s'",
"keras" if self._backend == "amd" else "tf.keras", self._backend)
path = sys.path if path is None else path
for entry in path:
locations = ([os.path.join(entry, *location)
for location in self._tf_keras_locations]
if self._backend != "amd" else [entry])
for location in locations:
self._logger.debug("Scanning: '%s' for '%s'", location, suffix)
if os.path.isdir(os.path.join(location, suffix)):
filename = os.path.join(location, suffix, "__init__.py")
submodule_locations = [os.path.join(location, suffix)]
else:
filename = os.path.join(location, suffix + ".py")
submodule_locations = None
if not os.path.exists(filename):
continue
retval = importlib.util.spec_from_file_location(
fullname,
filename,
submodule_search_locations=submodule_locations)
self._logger.debug("Found spec: %s", retval)
return retval
self._logger.debug("Spec not found for '%s'. Falling back to default import", fullname)
return None

View file

@ -5,11 +5,17 @@ from __future__ import absolute_import, division, print_function
import cv2
import numpy as np
# pylint:disable=import-error
from keras.layers import Conv2D, Dense, Flatten, Input, MaxPool2D, Permute, PReLU
from lib.model.session import KSession
from lib.utils import get_backend
from ._base import Detector, logger
if get_backend() == "amd":
from keras.layers import Conv2D, Dense, Flatten, Input, MaxPool2D, Permute, PReLU
else:
# Ignore linting errors from Tensorflow's thoroughly broken import system
from tensorflow.keras.layers import Conv2D, Dense, Flatten, Input, MaxPool2D, Permute, PReLU # noqa pylint:disable=no-name-in-module,import-error
class Detect(Detector):
""" MTCNN detector for face recognition """
@ -234,8 +240,8 @@ class MTCNN():
rectangles = self.detect_pnet(batch, origin_h, origin_w)
rectangles = self.detect_rnet(batch, rectangles, origin_h, origin_w)
rectangles = self.detect_onet(batch, rectangles, origin_h, origin_w)
ret_boxes = list()
ret_points = list()
ret_boxes = []
ret_points = []
for rects in rectangles:
if rects:
total_boxes = np.array([result[:5] for result in rects])
@ -284,7 +290,7 @@ class MTCNN():
# TODO: batching
for idx, rectangles in enumerate(rectangle_batch):
if not rectangles:
ret.append(list())
ret.append([])
continue
image = images[idx]
crop_number = 0
@ -307,11 +313,11 @@ class MTCNN():
def detect_onet(self, images, rectangle_batch, height, width):
""" third stage - further refinement and facial landmarks positions with o-net """
ret = list()
ret = []
# TODO: batching
for idx, rectangles in enumerate(rectangle_batch):
if not rectangles:
ret.append(list())
ret.append([])
continue
image = images[idx]
crop_number = 0

View file

@ -8,13 +8,22 @@ https://github.com/1adrianb/face-alignment
from scipy.special import logsumexp
import numpy as np
import keras # pylint:disable=import-error
import keras.backend as K # pylint:disable=import-error
from keras.layers import Concatenate, Conv2D, Input, Maximum, MaxPooling2D, ZeroPadding2D
from lib.model.session import KSession
from lib.utils import get_backend
from ._base import Detector, logger
if get_backend() == "amd":
import keras
from keras import backend as K
from keras.layers import Concatenate, Conv2D, Input, Maximum, MaxPooling2D, ZeroPadding2D
else:
# Ignore linting errors from Tensorflow's thoroughly broken import system
from tensorflow import keras
from tensorflow.keras import backend as K # pylint:disable=import-error
from tensorflow.keras.layers import ( # pylint:disable=no-name-in-module,import-error
Concatenate, Conv2D, Input, Maximum, MaxPooling2D, ZeroPadding2D)
class Detect(Detector):
""" S3FD detector for face recognition """
@ -316,11 +325,11 @@ class S3fd(KSession):
tensor
The output tensor from the convolution block
"""
name = "conv{}".format(idx)
name = f"conv{idx}"
var_x = inputs
for i in range(1, recursions + 1):
rec_name = "{}_{}".format(name, i)
var_x = ZeroPadding2D(1, name="{}.zeropad".format(rec_name))(var_x)
rec_name = f"{name}_{i}"
var_x = ZeroPadding2D(1, name=f"{rec_name}.zeropad")(var_x)
var_x = Conv2D(filters,
kernel_size=3,
strides=1,
@ -346,13 +355,13 @@ class S3fd(KSession):
tensor
The output tensor from the convolution block
"""
name = "conv{}".format(idx)
name = f"conv{idx}"
var_x = inputs
for i in range(1, 3):
rec_name = "{}_{}".format(name, i)
rec_name = f"{name}_{i}"
size = 1 if i == 1 else 3
if i == 2:
var_x = ZeroPadding2D(1, name="{}.zeropad".format(rec_name))(var_x)
var_x = ZeroPadding2D(1, name=f"{rec_name}.zeropad")(var_x)
var_x = Conv2D(filters * i,
kernel_size=size,
strides=i,
@ -386,7 +395,7 @@ class S3fd(KSession):
bounding_boxes_scales: list
The output predictions from the S3FD model
"""
ret = list()
ret = []
batch_size = range(bounding_boxes_scales[0].shape[0])
for img in batch_size:
bboxlist = [scale[img:img+1] for scale in bounding_boxes_scales]
@ -399,7 +408,7 @@ class S3fd(KSession):
""" Perform post processing on output
TODO: do this on the batch.
"""
retval = list()
retval = []
for i in range(len(bboxlist) // 2):
bboxlist[i * 2] = self.softmax(bboxlist[i * 2], axis=3)
for i in range(len(bboxlist) // 2):
@ -450,7 +459,7 @@ class S3fd(KSession):
@staticmethod
def _nms(boxes, threshold):
""" Perform Non-Maximum Suppression """
retained_box_indices = list()
retained_box_indices = []
areas = (boxes[:, 2] - boxes[:, 0] + 1) * (boxes[:, 3] - boxes[:, 1] + 1)
ranked_indices = boxes[:, 4].argsort()[::-1]

View file

@ -6,15 +6,23 @@ https://github.com/zllrunning/face-parsing.PyTorch
"""
import numpy as np
from keras import backend as K
from keras.layers import (Activation, Add, BatchNormalization, Concatenate, Conv2D,
GlobalAveragePooling2D, Input, MaxPooling2D, Multiply, Reshape,
UpSampling2D, ZeroPadding2D)
from lib.model.session import KSession
from lib.utils import get_backend
from plugins.extract._base import _get_config
from ._base import Masker, logger
if get_backend() == "amd":
from keras import backend as K
from keras.layers import (
Activation, Add, BatchNormalization, Concatenate, Conv2D, GlobalAveragePooling2D, Input,
MaxPooling2D, Multiply, Reshape, UpSampling2D, ZeroPadding2D)
else:
# Ignore linting errors from Tensorflow's thoroughly broken import system
from tensorflow.keras import backend as K # pylint:disable=import-error
from tensorflow.keras.layers import ( # pylint:disable=no-name-in-module,import-error
Activation, Add, BatchNormalization, Concatenate, Conv2D, GlobalAveragePooling2D, Input,
MaxPooling2D, Multiply, Reshape, UpSampling2D, ZeroPadding2D)
class Mask(Masker):
""" Neural network to process face image into a segmentation mask of the face """

View file

@ -2,13 +2,21 @@
""" VGG Clear face mask plugin. """
import numpy as np
from keras.layers import (Add, Conv2D, # pylint:disable=no-name-in-module,import-error
Conv2DTranspose, Cropping2D, Dropout, Input, Lambda,
MaxPooling2D, ZeroPadding2D)
from lib.model.session import KSession
from lib.utils import get_backend
from ._base import Masker, logger
if get_backend() == "amd":
from keras.layers import (
Add, Conv2D, Conv2DTranspose, Cropping2D, Dropout, Input, Lambda, MaxPooling2D,
ZeroPadding2D)
else:
# Ignore linting errors from Tensorflow's thoroughly broken import system
from tensorflow.keras.layers import ( # pylint:disable=no-name-in-module,import-error
Add, Conv2D, Conv2DTranspose, Cropping2D, Dropout, Input, Lambda, MaxPooling2D,
ZeroPadding2D)
class Mask(Masker):
""" Neural network to process face image into a segmentation mask of the face """
@ -151,7 +159,7 @@ class _ConvBlock(): # pylint:disable=too-few-public-methods
The number of consecutive Conv2D layers to create
"""
def __init__(self, level, filters, iterations):
self._name = "conv{}_".format(level)
self._name = f"conv{level}_"
self._level = level
self._filters = filters
self._iterator = range(1, iterations + 1)
@ -176,10 +184,10 @@ class _ConvBlock(): # pylint:disable=too-few-public-methods
3,
padding=padding,
activation="relu",
name="{}{}".format(self._name, i))(var_x)
name=f"{self._name}{i}")(var_x)
var_x = MaxPooling2D(padding="same",
strides=(2, 2),
name="pool{}".format(self._level))(var_x)
name=f"pool{self._level}")(var_x)
return var_x
@ -196,7 +204,7 @@ class _ScorePool(): # pylint:disable=too-few-public-methods
The amount of 2D cropping to apply. Tuple of `ints`
"""
def __init__(self, level, scale, crop):
self._name = "_pool{}".format(level)
self._name = f"_pool{level}"
self._cropping = (crop, crop)
self._scale = scale

View file

@ -2,13 +2,22 @@
""" VGG Obstructed face mask plugin """
import numpy as np
from keras.layers import (Add, Conv2D, # pylint:disable=no-name-in-module,import-error
Conv2DTranspose, Cropping2D, Dropout, Input, Lambda, MaxPooling2D,
ZeroPadding2D)
from lib.model.session import KSession
from lib.utils import get_backend
from ._base import Masker, logger
if get_backend() == "amd":
from keras.layers import (
Add, Conv2D, Conv2DTranspose, Cropping2D, Dropout, Input, Lambda, MaxPooling2D,
ZeroPadding2D)
else:
# Ignore linting errors from Tensorflow's thoroughly broken import system
from tensorflow.keras.layers import ( # pylint:disable=no-name-in-module,import-error
Add, Conv2D, Conv2DTranspose, Cropping2D, Dropout, Input, Lambda, MaxPooling2D,
ZeroPadding2D)
class Mask(Masker):
""" Neural network to process face image into a segmentation mask of the face """
@ -150,7 +159,7 @@ class _ConvBlock(): # pylint:disable=too-few-public-methods
The number of consecutive Conv2D layers to create
"""
def __init__(self, level, filters, iterations):
self._name = "conv{}_".format(level)
self._name = f"conv{level}_"
self._level = level
self._filters = filters
self._iterator = range(1, iterations + 1)
@ -175,10 +184,10 @@ class _ConvBlock(): # pylint:disable=too-few-public-methods
3,
padding=padding,
activation="relu",
name="{}{}".format(self._name, i))(var_x)
name=f"{self._name}{i}")(var_x)
var_x = MaxPooling2D(padding="same",
strides=(2, 2),
name="pool{}".format(self._level))(var_x)
name=f"pool{self._level}")(var_x)
return var_x
@ -195,7 +204,7 @@ class _ScorePool(): # pylint:disable=too-few-public-methods
The amount of 2D cropping to apply
"""
def __init__(self, level, scale, crop):
self._name = "_pool{}".format(level)
self._name = f"_pool{level}"
self._cropping = ((crop, crop), (crop, crop))
self._scale = scale

View file

@ -16,11 +16,6 @@ from contextlib import nullcontext
import numpy as np
import tensorflow as tf
from keras import losses as k_losses
from keras import backend as K
from keras.layers import Input
from keras.models import load_model, Model as KModel
from lib.serializer import get_serializer
from lib.model.backup_restore import Backup
from lib.model import losses, optimizers
@ -28,6 +23,19 @@ from lib.model.nn_blocks import set_config as set_nnblock_config
from lib.utils import get_backend, get_tf_version, FaceswapError
from plugins.train._config import Config
if get_backend() == "amd":
from keras import losses as k_losses
from keras import backend as K
from keras.layers import Input
from keras.models import load_model, Model as KModel
else:
# Ignore linting errors from Tensorflow's thoroughly broken import system
from tensorflow.keras import losses as k_losses # pylint:disable=import-error
from tensorflow.keras import backend as K # pylint:disable=import-error
from tensorflow.keras.layers import Input # pylint:disable=import-error,no-name-in-module
from tensorflow.keras.models import load_model, Model as KModel # noqa pylint:disable=import-error,no-name-in-module
logger = logging.getLogger(__name__) # pylint: disable=invalid-name
_CONFIG = None

View file

@ -4,12 +4,19 @@
import logging
import sys
from keras.initializers import RandomNormal
from keras.layers import Input, LeakyReLU
from lib.model.nn_blocks import Conv2DOutput, UpscaleBlock, ResidualBlock
from lib.utils import get_backend
from .original import Model as OriginalModel, KerasModel
if get_backend() == "amd":
from keras.initializers import RandomNormal
from keras.layers import Input, LeakyReLU
else:
# Ignore linting errors from Tensorflow's thoroughly broken import system
from tensorflow.keras.initializers import RandomNormal # noqa pylint:disable=import-error,no-name-in-module
from tensorflow.keras.layers import Input, LeakyReLU # noqa pylint:disable=import-error,no-name-in-module
logger = logging.getLogger(__name__) # pylint: disable=invalid-name
@ -44,7 +51,7 @@ class Model(OriginalModel):
var_x = LeakyReLU(alpha=0.2)(var_x)
var_x = ResidualBlock(128, kernel_initializer=self.kernel_initializer)(var_x)
var_x = UpscaleBlock(64, activation="leakyrelu")(var_x)
var_x = Conv2DOutput(3, 5, name="face_out_{}".format(side))(var_x)
var_x = Conv2DOutput(3, 5, name=f"face_out_{side}")(var_x)
outputs = [var_x]
if self.config.get("learn_mask", False):
@ -55,6 +62,6 @@ class Model(OriginalModel):
var_y = UpscaleBlock(256, activation="leakyrelu")(var_y)
var_y = UpscaleBlock(128, activation="leakyrelu")(var_y)
var_y = UpscaleBlock(64, activation="leakyrelu")(var_y)
var_y = Conv2DOutput(1, 5, name="mask_out_{}".format(side))(var_y)
var_y = Conv2DOutput(1, 5, name=f"mask_out_{side}")(var_y)
outputs.append(var_y)
return KerasModel([input_], outputs=outputs, name="decoder_{}".format(side))
return KerasModel([input_], outputs=outputs, name=f"decoder_{side}")

View file

@ -3,11 +3,16 @@
Based on https://github.com/iperov/DeepFaceLab
"""
from keras.layers import Dense, Flatten, Input, Reshape
from lib.model.nn_blocks import Conv2DOutput, Conv2DBlock, UpscaleBlock
from lib.utils import get_backend
from .original import Model as OriginalModel, KerasModel
if get_backend() == "amd":
from keras.layers import Dense, Flatten, Input, Reshape
else:
# Ignore linting errors from Tensorflow's thoroughly broken import system
from tensorflow.keras.layers import Dense, Flatten, Input, Reshape # noqa pylint:disable=import-error,no-name-in-module
class Model(OriginalModel):
""" H128 Model from DFL """
@ -36,7 +41,7 @@ class Model(OriginalModel):
var_x = UpscaleBlock(self.encoder_dim, activation="leakyrelu")(var_x)
var_x = UpscaleBlock(self.encoder_dim // 2, activation="leakyrelu")(var_x)
var_x = UpscaleBlock(self.encoder_dim // 4, activation="leakyrelu")(var_x)
var_x = Conv2DOutput(3, 5, name="face_out_{}".format(side))(var_x)
var_x = Conv2DOutput(3, 5, name=f"face_out_{side}")(var_x)
outputs = [var_x]
if self.config.get("learn_mask", False):
@ -44,6 +49,6 @@ class Model(OriginalModel):
var_y = UpscaleBlock(self.encoder_dim, activation="leakyrelu")(var_y)
var_y = UpscaleBlock(self.encoder_dim // 2, activation="leakyrelu")(var_y)
var_y = UpscaleBlock(self.encoder_dim // 4, activation="leakyrelu")(var_y)
var_y = Conv2DOutput(1, 5, name="mask_out_{}".format(side))(var_y)
var_y = Conv2DOutput(1, 5, name=f"mask_out_{side}")(var_y)
outputs.append(var_y)
return KerasModel(input_, outputs=outputs, name="decoder_{}".format(side))
return KerasModel(input_, outputs=outputs, name=f"decoder_{side}")

View file

@ -5,12 +5,17 @@
import numpy as np
from keras.layers import Concatenate, Dense, Flatten, Input, LeakyReLU, Reshape
from lib.model.nn_blocks import Conv2DOutput, Conv2DBlock, ResidualBlock, UpscaleBlock
from lib.utils import get_backend
from ._base import ModelBase, KerasModel, logger
if get_backend() == "amd":
from keras.layers import Concatenate, Dense, Flatten, Input, LeakyReLU, Reshape
else:
# Ignore linting errors from Tensorflow's thoroughly broken import system
from tensorflow.keras.layers import Concatenate, Dense, Flatten, Input, LeakyReLU, Reshape # noqa pylint:disable=import-error,no-name-in-module
class Model(ModelBase):
""" SAE Model from DFL """
@ -50,7 +55,7 @@ class Model(ModelBase):
def build_model(self, inputs):
""" Build the DFL-SAE Model """
encoder = getattr(self, "encoder_{}".format(self.architecture))()
encoder = getattr(self, f"encoder_{self.architecture}")()
enc_output_shape = encoder.output_shape[1:]
encoder_a = encoder(inputs[0])
encoder_b = encoder(inputs[1])
@ -108,7 +113,7 @@ class Model(ModelBase):
var_x = Dense(lowest_dense_res * lowest_dense_res * self.ae_dims * 2)(var_x)
var_x = Reshape((lowest_dense_res, lowest_dense_res, self.ae_dims * 2))(var_x)
var_x = UpscaleBlock(self.ae_dims * 2, activation="leakyrelu")(var_x)
return KerasModel(input_, var_x, name="intermediate_{}".format(side))
return KerasModel(input_, var_x, name=f"intermediate_{side}")
def decoder(self, side, input_shape):
""" DFL SAE Decoder Network"""
@ -123,38 +128,38 @@ class Model(ModelBase):
var_x1 = ResidualBlock(dims * 8)(var_x1)
var_x1 = ResidualBlock(dims * 8)(var_x1)
if self.multiscale_count >= 3:
outputs.append(Conv2DOutput(3, 5, name="face_out_32_{}".format(side))(var_x1))
outputs.append(Conv2DOutput(3, 5, name=f"face_out_32_{side}")(var_x1))
var_x2 = UpscaleBlock(dims * 4, activation=None)(var_x1)
var_x2 = LeakyReLU(alpha=0.2)(var_x2)
var_x2 = ResidualBlock(dims * 4)(var_x2)
var_x2 = ResidualBlock(dims * 4)(var_x2)
if self.multiscale_count >= 2:
outputs.append(Conv2DOutput(3, 5, name="face_out_64_{}".format(side))(var_x2))
outputs.append(Conv2DOutput(3, 5, name=f"face_out_64_{side}")(var_x2))
var_x3 = UpscaleBlock(dims * 2, activation=None)(var_x2)
var_x3 = LeakyReLU(alpha=0.2)(var_x3)
var_x3 = ResidualBlock(dims * 2)(var_x3)
var_x3 = ResidualBlock(dims * 2)(var_x3)
outputs.append(Conv2DOutput(3, 5, name="face_out_128_{}".format(side))(var_x3))
outputs.append(Conv2DOutput(3, 5, name=f"face_out_128_{side}")(var_x3))
if self.use_mask:
var_y = input_
var_y = UpscaleBlock(self.decoder_dim * 8, activation="leakyrelu")(var_y)
var_y = UpscaleBlock(self.decoder_dim * 4, activation="leakyrelu")(var_y)
var_y = UpscaleBlock(self.decoder_dim * 2, activation="leakyrelu")(var_y)
var_y = Conv2DOutput(1, 5, name="mask_out_{}".format(side))(var_y)
var_y = Conv2DOutput(1, 5, name=f"mask_out_{side}")(var_y)
outputs.append(var_y)
return KerasModel(input_, outputs=outputs, name="decoder_{}".format(side))
return KerasModel(input_, outputs=outputs, name=f"decoder_{side}")
def _legacy_mapping(self):
""" The mapping of legacy separate model names to single model names """
mappings = dict(df={"{}_encoder.h5".format(self.name): "encoder_df",
"{}_decoder_A.h5".format(self.name): "decoder_a",
"{}_decoder_B.h5".format(self.name): "decoder_b"},
liae={"{}_encoder.h5".format(self.name): "encoder_liae",
"{}_intermediate_B.h5".format(self.name): "intermediate_both",
"{}_intermediate.h5".format(self.name): "intermediate_b",
"{}_decoder.h5".format(self.name): "decoder_both"})
mappings = dict(df={f"{self.name}_encoder.h5": "encoder_df",
f"{self.name}_decoder_A.h5": "decoder_a",
f"{self.name}_decoder_B.h5": "decoder_b"},
liae={f"{self.name}_encoder.h5": "encoder_liae",
f"{self.name}_intermediate_B.h5": "intermediate_both",
f"{self.name}_intermediate.h5": "intermediate_b",
f"{self.name}_decoder.h5": "decoder_both"})
return mappings[self.config["architecture"]]

View file

@ -8,15 +8,22 @@
DeepHomage for lots of testing
"""
from keras.layers import (AveragePooling2D, BatchNormalization, Concatenate, Dense, Dropout,
Flatten, Input, Reshape, LeakyReLU, UpSampling2D)
from lib.model.nn_blocks import (Conv2DOutput, Conv2DBlock, ResidualBlock, UpscaleBlock,
Upscale2xBlock)
from lib.utils import FaceswapError
from lib.utils import FaceswapError, get_backend
from ._base import ModelBase, KerasModel, logger
if get_backend() == "amd":
from keras.layers import (
AveragePooling2D, BatchNormalization, Concatenate, Dense, Dropout, Flatten, Input, Reshape,
LeakyReLU, UpSampling2D)
else:
# Ignore linting errors from Tensorflow's thoroughly broken import system
from tensorflow.keras.layers import ( # pylint:disable=import-error,no-name-in-module
AveragePooling2D, BatchNormalization, Concatenate, Dense, Dropout, Flatten, Input, Reshape,
LeakyReLU, UpSampling2D)
class Model(ModelBase):
""" DLight Autoencoder Model """
@ -218,6 +225,6 @@ class Model(ModelBase):
def _legacy_mapping(self):
""" The mapping of legacy separate model names to single model names """
decoder_b = "decoder_b" if self.details > 0 else "decoder_b_fast"
return {"{}_encoder.h5".format(self.name): "encoder",
"{}_decoder_A.h5".format(self.name): "decoder_a",
"{}_decoder_B.h5".format(self.name): decoder_b}
return {f"{self.name}_encoder.h5": "encoder",
f"{self.name}_decoder_A.h5": "decoder_a",
f"{self.name}_decoder_B.h5": decoder_b}

View file

@ -1,11 +1,18 @@
#!/usr/bin/env python3
""" Improved autoencoder for faceswap """
from keras.layers import Concatenate, Dense, Flatten, Input, Reshape
from lib.model.nn_blocks import Conv2DOutput, Conv2DBlock, UpscaleBlock
from lib.utils import get_backend
from ._base import ModelBase, KerasModel
if get_backend() == "amd":
from keras.layers import Concatenate, Dense, Flatten, Input, Reshape
else:
# Ignore linting errors from Tensorflow's thoroughly broken import system
from tensorflow.keras.layers import Concatenate, Dense, Flatten, Input, Reshape # noqa pylint:disable=import-error,no-name-in-module
class Model(ModelBase):
""" Improved Autoencoder Model """
@ -48,7 +55,7 @@ class Model(ModelBase):
var_x = Dense(self.encoder_dim)(input_)
var_x = Dense(4 * 4 * int(self.encoder_dim/2))(var_x)
var_x = Reshape((4, 4, int(self.encoder_dim/2)))(var_x)
return KerasModel(input_, var_x, name="inter_{}".format(side))
return KerasModel(input_, var_x, name=f"inter_{side}")
def decoder(self):
""" Decoder Network """
@ -73,8 +80,8 @@ class Model(ModelBase):
def _legacy_mapping(self):
""" The mapping of legacy separate model names to single model names """
return {"{}_encoder.h5".format(self.name): "encoder",
"{}_intermediate_A.h5".format(self.name): "inter_a",
"{}_intermediate_B.h5".format(self.name): "inter_b",
"{}_inter.h5".format(self.name): "inter_both",
"{}_decoder.h5".format(self.name): "decoder"}
return {f"{self.name}_encoder.h5": "encoder",
f"{self.name}_intermediate_A.h5": "inter_a",
f"{self.name}_intermediate_B.h5": "inter_b",
f"{self.name}_inter.h5": "inter_both",
f"{self.name}_decoder.h5": "decoder"}

View file

@ -4,10 +4,8 @@
Based on the original https://www.reddit.com/r/deepfakes/
code sample + contributions """
from keras.layers import Dense, Flatten, Input, Reshape
from lib.model.nn_blocks import Conv2DOutput, Conv2DBlock, UpscaleBlock
from .original import Model as OriginalModel, KerasModel
from .original import Model as OriginalModel, KerasModel, Dense, Flatten, Input, Reshape
class Model(OriginalModel):
@ -36,7 +34,7 @@ class Model(OriginalModel):
var_x = UpscaleBlock(512, activation="leakyrelu")(var_x)
var_x = UpscaleBlock(256, activation="leakyrelu")(var_x)
var_x = UpscaleBlock(128, activation="leakyrelu")(var_x)
var_x = Conv2DOutput(3, 5, activation="sigmoid", name="face_out_{}".format(side))(var_x)
var_x = Conv2DOutput(3, 5, activation="sigmoid", name=f"face_out_{side}")(var_x)
outputs = [var_x]
if self.config.get("learn_mask", False):
@ -46,6 +44,6 @@ class Model(OriginalModel):
var_y = UpscaleBlock(128, activation="leakyrelu")(var_y)
var_y = Conv2DOutput(1, 5,
activation="sigmoid",
name="mask_out_{}".format(side))(var_y)
name=f"mask_out_{side}")(var_y)
outputs.append(var_y)
return KerasModel(input_, outputs=outputs, name="decoder_{}".format(side))
return KerasModel(input_, outputs=outputs, name=f"decoder_{side}")

View file

@ -5,11 +5,17 @@ Based on the original https://www.reddit.com/r/deepfakes/ code sample + contribu
This model is heavily documented as it acts as a template that other model plugins can be developed
from.
"""
from keras.layers import Dense, Flatten, Reshape, Input
from lib.model.nn_blocks import Conv2DOutput, Conv2DBlock, UpscaleBlock
from lib.utils import get_backend
from ._base import KerasModel, ModelBase
if get_backend() == "amd":
from keras.layers import Dense, Flatten, Reshape, Input
else:
# Ignore linting errors from Tensorflow's thoroughly broken import system
from tensorflow.keras.layers import Dense, Flatten, Reshape, Input # noqa pylint:disable=import-error,no-name-in-module
class Model(ModelBase):
""" Original Faceswap Model.
@ -144,7 +150,7 @@ class Model(ModelBase):
var_x = UpscaleBlock(256, activation="leakyrelu")(var_x)
var_x = UpscaleBlock(128, activation="leakyrelu")(var_x)
var_x = UpscaleBlock(64, activation="leakyrelu")(var_x)
var_x = Conv2DOutput(3, 5, name="face_out_{}".format(side))(var_x)
var_x = Conv2DOutput(3, 5, name=f"face_out_{side}")(var_x)
outputs = [var_x]
if self.learn_mask:
@ -152,12 +158,12 @@ class Model(ModelBase):
var_y = UpscaleBlock(256, activation="leakyrelu")(var_y)
var_y = UpscaleBlock(128, activation="leakyrelu")(var_y)
var_y = UpscaleBlock(64, activation="leakyrelu")(var_y)
var_y = Conv2DOutput(1, 5, name="mask_out_{}".format(side))(var_y)
var_y = Conv2DOutput(1, 5, name=f"mask_out_{side}")(var_y)
outputs.append(var_y)
return KerasModel(input_, outputs=outputs, name="decoder_{}".format(side))
return KerasModel(input_, outputs=outputs, name=f"decoder_{side}")
def _legacy_mapping(self):
""" The mapping of legacy separate model names to single model names """
return {"{}_encoder.h5".format(self.name): "encoder",
"{}_decoder_A.h5".format(self.name): "decoder_a",
"{}_decoder_B.h5".format(self.name): "decoder_b"}
return {f"{self.name}_encoder.h5": "encoder",
f"{self.name}_decoder_A.h5": "decoder_a",
f"{self.name}_decoder_B.h5": "decoder_b"}

View file

@ -4,29 +4,32 @@
import numpy as np
import tensorflow as tf
import keras.backend as K
from keras.layers import (
Add, BatchNormalization, Concatenate, Dense, Dropout, Flatten, GaussianNoise,
GlobalAveragePooling2D, GlobalMaxPooling2D, Input, LeakyReLU, Reshape, UpSampling2D,
Conv2D as KConv2D)
from keras.models import clone_model
from lib.model.nn_blocks import (
Conv2D, Conv2DBlock, Conv2DOutput, ResidualBlock, UpscaleBlock, Upscale2xBlock,
UpscaleResizeImagesBlock)
from lib.model.normalization import (
AdaInstanceNormalization, GroupNormalization, InstanceNormalization, LayerNormalization,
RMSNormalization)
from lib.utils import get_backend, FaceswapError
if get_backend() == "amd":
from keras import applications as kapp
else:
from tensorflow.keras import applications as kapp
from ._base import KerasModel, ModelBase, logger, _get_all_sub_models
if get_backend() == "amd":
from keras import applications as kapp, backend as K
from keras.layers import (
Add, BatchNormalization, Concatenate, Dense, Dropout, Flatten, GaussianNoise,
GlobalAveragePooling2D, GlobalMaxPooling2D, Input, LeakyReLU, Reshape, UpSampling2D,
Conv2D as KConv2D)
from keras.models import clone_model
else:
# Ignore linting errors from Tensorflow's thoroughly broken import system
from tensorflow.keras import applications as kapp, backend as K # pylint:disable=import-error
from tensorflow.keras.layers import ( # pylint:disable=import-error,no-name-in-module
Add, BatchNormalization, Concatenate, Dense, Dropout, Flatten, GaussianNoise,
GlobalAveragePooling2D, GlobalMaxPooling2D, Input, LeakyReLU, Reshape, UpSampling2D,
Conv2D as KConv2D)
from tensorflow.keras.models import clone_model # noqa pylint:disable=import-error,no-name-in-module
_MODEL_MAPPING = dict(
densenet121=dict(
@ -231,7 +234,7 @@ class Model(ModelBase):
f"one of {list(_MODEL_MAPPING.keys())}.")
if get_backend() == "amd" and model.get("no_amd"):
valid = [x for x in _MODEL_MAPPING if not _MODEL_MAPPING[x].get('no_amd')]
valid = [k for k, v in _MODEL_MAPPING.items() if not v.get('no_amd')]
raise FaceswapError(f"'{arch}' is not compatible with the AMD backend. Choose one of "
f"{valid}.")
@ -553,7 +556,7 @@ class Encoder(): # pylint:disable=too-few-public-methods
""" dict: The selected encoder model options dictionary """
arch = self._config["enc_architecture"]
model = _MODEL_MAPPING.get(arch)
model["kwargs"] = self._model_kwargs.get(arch, dict())
model["kwargs"] = self._model_kwargs.get(arch, {})
return model
@property
@ -804,7 +807,7 @@ class FullyConnected(): # pylint:disable=too-few-public-methods
if self._config["fc_upsampler"].lower() == "upsample2d":
var_x = LeakyReLU(alpha=0.1)(var_x)
return KerasModel(input_, var_x, name="fc_{}".format(self._side))
return KerasModel(input_, var_x, name=f"fc_{self._side}")
class GBlock(): # pylint:disable=too-few-public-methods
@ -1028,4 +1031,4 @@ class Decoder(): # pylint:disable=too-few-public-methods
self._config["dec_output_kernel"],
name="mask_out")(var_y))
return KerasModel(inputs, outputs=outputs, name="decoder_{}".format(self._side))
return KerasModel(inputs, outputs=outputs, name=f"decoder_{self._side}")

View file

@ -9,13 +9,18 @@
"""
import sys
from keras.initializers import RandomNormal
from keras.layers import Dense, Flatten, Input, LeakyReLU, Reshape
from lib.model.nn_blocks import Conv2DOutput, Conv2DBlock, ResidualBlock, UpscaleBlock
from lib.utils import get_backend
from ._base import ModelBase, KerasModel, logger
if get_backend() == "amd":
from keras.initializers import RandomNormal
from keras.layers import Dense, Flatten, Input, LeakyReLU, Reshape
else:
# Ignore linting errors from Tensorflow's thoroughly broken import system
from tensorflow.keras.initializers import RandomNormal # noqa pylint:disable=import-error,no-name-in-module
from tensorflow.keras.layers import Dense, Flatten, Input, LeakyReLU, Reshape # noqa pylint:disable=import-error,no-name-in-module
class Model(ModelBase):
""" RealFace(tm) Faceswap Model """
@ -183,6 +188,6 @@ class Model(ModelBase):
def _legacy_mapping(self):
""" The mapping of legacy separate model names to single model names """
return {"{}_encoder.h5".format(self.name): "encoder",
"{}_decoder_A.h5".format(self.name): "decoder_a",
"{}_decoder_B.h5".format(self.name): "decoder_b"}
return {f"{self.name}_encoder.h5": "encoder",
f"{self.name}_decoder_A.h5": "decoder_a",
f"{self.name}_decoder_B.h5": "decoder_b"}

View file

@ -3,12 +3,18 @@
Based on the original https://www.reddit.com/r/deepfakes/
code sample + contributions """
from keras.initializers import RandomNormal
from keras.layers import Dense, Flatten, Input, LeakyReLU, Reshape, SpatialDropout2D
from lib.model.nn_blocks import Conv2DOutput, Conv2DBlock, ResidualBlock, UpscaleBlock
from lib.utils import get_backend
from ._base import ModelBase, KerasModel
if get_backend() == "amd":
from keras.initializers import RandomNormal
from keras.layers import Dense, Flatten, Input, LeakyReLU, Reshape, SpatialDropout2D
else:
# Ignore linting errors from Tensorflow's thoroughly broken import system
from tensorflow.keras.initializers import RandomNormal # noqa pylint:disable=import-error,no-name-in-module
from tensorflow.keras.layers import Dense, Flatten, Input, LeakyReLU, Reshape, SpatialDropout2D # noqa pylint:disable=import-error,no-name-in-module
class Model(ModelBase):
""" Unbalanced Faceswap Model """
@ -135,6 +141,6 @@ class Model(ModelBase):
def _legacy_mapping(self):
""" The mapping of legacy separate model names to single model names """
return {"{}_encoder.h5".format(self.name): "encoder",
"{}_decoder_A.h5".format(self.name): "decoder_a",
"{}_decoder_B.h5".format(self.name): "decoder_b"}
return {f"{self.name}_encoder.h5": "encoder",
f"{self.name}_decoder_A.h5": "decoder_a",
f"{self.name}_decoder_B.h5": "decoder_b"}

View file

@ -3,14 +3,21 @@
Based on the original https://www.reddit.com/r/deepfakes/ code sample + contributions
Adapted from a model by VillainGuy (https://github.com/VillainGuy) """
from keras.initializers import RandomNormal
from keras.layers import add, Dense, Flatten, Input, LeakyReLU, Reshape
from lib.model.layers import PixelShuffler
from lib.model.nn_blocks import (Conv2DOutput, Conv2DBlock, ResidualBlock, SeparableConv2DBlock,
UpscaleBlock)
from lib.utils import get_backend
from .original import Model as OriginalModel, KerasModel
if get_backend() == "amd":
from keras.initializers import RandomNormal
from keras.layers import add, Dense, Flatten, Input, LeakyReLU, Reshape
else:
# Ignore linting errors from Tensorflow's thoroughly broken import system
from tensorflow.keras.initializers import RandomNormal # noqa pylint:disable=import-error,no-name-in-module
from tensorflow.keras.layers import add, Dense, Flatten, Input, LeakyReLU, Reshape # noqa pylint:disable=import-error,no-name-in-module
class Model(OriginalModel):
""" Villain Faceswap Model """
@ -72,7 +79,7 @@ class Model(OriginalModel):
var_x = UpscaleBlock(self.input_shape[0], activation=None, **kwargs)(var_x)
var_x = LeakyReLU(alpha=0.2)(var_x)
var_x = ResidualBlock(self.input_shape[0], **kwargs)(var_x)
var_x = Conv2DOutput(3, 5, name="face_out_{}".format(side))(var_x)
var_x = Conv2DOutput(3, 5, name=f"face_out_{side}")(var_x)
outputs = [var_x]
if self.config.get("learn_mask", False):
@ -80,6 +87,6 @@ class Model(OriginalModel):
var_y = UpscaleBlock(512, activation="leakyrelu")(var_y)
var_y = UpscaleBlock(256, activation="leakyrelu")(var_y)
var_y = UpscaleBlock(self.input_shape[0], activation="leakyrelu")(var_y)
var_y = Conv2DOutput(1, 5, name="mask_out_{}".format(side))(var_y)
var_y = Conv2DOutput(1, 5, name=f"mask_out_{side}")(var_y)
outputs.append(var_y)
return KerasModel(input_, outputs=outputs, name="decoder_{}".format(side))
return KerasModel(input_, outputs=outputs, name=f"decoder_{side}")

View file

@ -1,7 +0,0 @@
#!/usr/bin/env python3
""" Use custom Importer for importing Keras for tests """
import sys
from lib.utils import KerasFinder
sys.meta_path.insert(0, KerasFinder())

View file

@ -4,14 +4,21 @@
Adapted from Keras tests.
"""
from keras import backend as K
from keras import initializers as k_initializers
import pytest
import numpy as np
from lib.model import initializers
from lib.utils import get_backend
if get_backend() == "amd":
from keras import backend as K
from keras import initializers as k_initializers
else:
# Ignore linting errors from Tensorflow's thoroughly broken import system
from tensorflow.keras import backend as K # pylint:disable=import-error
from tensorflow.keras import initializers as k_initializers # pylint:disable=import-error
CONV_SHAPE = (3, 3, 256, 2048)
CONV_ID = get_backend().upper()

View file

@ -7,7 +7,6 @@ Adapted from Keras tests.
import pytest
import numpy as np
from keras import Input, Model, backend as K
from numpy.testing import assert_allclose
@ -15,6 +14,13 @@ from lib.model import layers
from lib.utils import get_backend
from tests.utils import has_arg
if get_backend() == "amd":
from keras import Input, Model, backend as K
else:
# Ignore linting errors from Tensorflow's thoroughly broken import system
from tensorflow.keras import Input, Model, backend as K # pylint:disable=import-error
CONV_SHAPE = (3, 3, 256, 2048)
CONV_ID = get_backend().upper()

View file

@ -6,17 +6,15 @@ Adapted from Keras tests.
import pytest
import numpy as np
from numpy.testing import assert_allclose
from keras import backend as K
from keras import losses as k_losses
from keras.layers import Conv2D
from keras.models import Sequential
from keras.optimizers import Adam
from lib.model import losses
from lib.utils import get_backend
if get_backend() == "amd":
from keras import backend as K, losses as k_losses
else:
# Ignore linting errors from Tensorflow's thoroughly broken import system
from tensorflow.keras import backend as K, losses as k_losses # pylint:disable=import-error
_PARAMS = [(losses.GeneralizedLoss(), (2, 16, 16)),
(losses.GradientLoss(), (2, 16, 16)),
@ -25,7 +23,7 @@ _PARAMS = [(losses.GeneralizedLoss(), (2, 16, 16)),
# TODO Make sure these output dimensions are correct
(losses.LInfNorm(), (2, 1, 1))]
_IDS = ["GeneralizedLoss", "GradientLoss", "GMSDLoss", "LInfNorm"]
_IDS = ["{}[{}]".format(loss, get_backend().upper()) for loss in _IDS]
_IDS = [f"{loss}[{get_backend().upper()}]" for loss in _IDS]
@pytest.mark.parametrize(["loss_func", "output_shape"], _PARAMS, ids=_IDS)
@ -48,7 +46,7 @@ _LWPARAMS = [losses.GeneralizedLoss(), losses.GradientLoss(), losses.GMSDLoss(),
k_losses.logcosh, losses.DSSIMObjective()]
_LWIDS = ["GeneralizedLoss", "GradientLoss", "GMSDLoss", "LInfNorm", "mae", "mse", "logcosh",
"DSSIMObjective"]
_LWIDS = ["{}[{}]".format(loss, get_backend().upper()) for loss in _LWIDS]
_LWIDS = [f"{loss}[{get_backend().upper()}]" for loss in _LWIDS]
@pytest.mark.parametrize("loss_func", _LWPARAMS, ids=_LWIDS)

View file

@ -9,12 +9,18 @@ from itertools import product
import pytest
import numpy as np
from keras import Input, Model, backend as K
from numpy.testing import assert_allclose
from lib.model import nn_blocks
from lib.utils import get_backend
if get_backend() == "amd":
from keras import Input, Model, backend as K
else:
# Ignore linting errors from Tensorflow's thoroughly broken import system
from tensorflow.keras import Input, Model, backend as K # pylint:disable=import-error
def block_test(layer_func, kwargs={}, input_shape=None):
"""Test routine for faceswap neural network blocks.

View file

@ -8,13 +8,17 @@ from itertools import product
import numpy as np
import pytest
from keras import regularizers, models, layers
from lib.model import normalization
from lib.utils import get_backend
from tests.lib.model.layers_test import layer_test
if get_backend() == "amd":
from keras import regularizers, models, layers
else:
# Ignore linting errors from Tensorflow's thoroughly broken import system
from tensorflow.keras import regularizers, models, layers # pylint:disable=import-error
@pytest.mark.parametrize('dummy', [None], ids=[get_backend().upper()])
def test_instance_normalization(dummy): # pylint:disable=unused-argument
@ -101,8 +105,7 @@ def test_layer_normalization(center, scale):
_PARAMS = ["partial", "bias"]
_VALUES = [(0.0, False), (0.25, False), (0.5, True), (0.75, False), (1.0, True)]
_IDS = ["partial={}|bias={}[{}]".format(v[0], v[1], get_backend().upper())
for v in _VALUES]
_IDS = [f"partial={v[0]}|bias={v[1]}[{get_backend().upper()}]" for v in _VALUES]
@pytest.mark.parametrize(_PARAMS, _VALUES, ids=_IDS)

View file

@ -5,9 +5,6 @@ Adapted from Keras tests.
"""
import pytest
from keras import optimizers as k_optimizers
from keras.layers import Dense, Activation
from keras.models import Sequential
import numpy as np
from numpy.testing import assert_allclose
@ -16,6 +13,16 @@ from lib.utils import get_backend
from tests.utils import generate_test_data, to_categorical
if get_backend() == "amd":
from keras import optimizers as k_optimizers
from keras.layers import Dense, Activation
from keras.models import Sequential
else:
# Ignore linting errors from Tensorflow's thoroughly broken import system
from tensorflow.keras import optimizers as k_optimizers # pylint:disable=import-error
from tensorflow.keras.layers import Dense, Activation # noqa pylint:disable=import-error,no-name-in-module
from tensorflow.keras.models import Sequential # pylint:disable=import-error,no-name-in-module
def get_test_data():
""" Obtain randomized test data for training """

View file

@ -5,11 +5,17 @@ import inspect
import pytest
import keras
from keras import backend as K
from lib.utils import get_backend
if get_backend() == "amd":
import keras
from keras import backend as K
else:
# Ignore linting errors from Tensorflow's thoroughly broken import system
from tensorflow import keras
from tensorflow.keras import backend as K # pylint:disable=import-error
_BACKEND = get_backend()