mirror of
https://github.com/iperov/DeepFaceLab.git
synced 2025-07-07 05:22:06 -07:00
Converter: added new mask modes: FAN-prd, FAN-dst
This commit is contained in:
parent
9849bcc1e5
commit
c4f41a7e76
5 changed files with 11426 additions and 11214 deletions
|
@ -2,6 +2,7 @@ import traceback
|
||||||
from .Converter import Converter
|
from .Converter import Converter
|
||||||
from facelib import LandmarksProcessor
|
from facelib import LandmarksProcessor
|
||||||
from facelib import FaceType
|
from facelib import FaceType
|
||||||
|
from facelib import FANSegmentator
|
||||||
import cv2
|
import cv2
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from utils import image_utils
|
from utils import image_utils
|
||||||
|
@ -65,9 +66,15 @@ class ConverterMasked(Converter):
|
||||||
|
|
||||||
if self.mode == 'hist-match' or self.mode == 'hist-match-bw' or self.mode == 'seamless-hist-match':
|
if self.mode == 'hist-match' or self.mode == 'hist-match-bw' or self.mode == 'seamless-hist-match':
|
||||||
self.hist_match_threshold = np.clip ( io.input_int("Hist match threshold [0..255] (skip:255) : ", 255), 0, 255)
|
self.hist_match_threshold = np.clip ( io.input_int("Hist match threshold [0..255] (skip:255) : ", 255), 0, 255)
|
||||||
|
|
||||||
|
if face_type == FaceType.FULL:
|
||||||
|
self.mask_mode = io.input_int ("Mask mode: (1) learned, (2) dst, (3) FAN-prd, (4) FAN-dst (?) help. Default - %d : " % (1) , 1, help_message="If you learned mask, then option 1 should be choosed. 'dst' mask is raw shaky mask from dst aligned images. 'FAN-prd' - using super smooth mask by pretrained FAN-model from predicted face. 'FAN-dst' - using super smooth mask by pretrained FAN-model from dst face.")
|
||||||
|
else:
|
||||||
|
self.mask_mode = io.input_int ("Mask mode: (1) learned, (2) dst . Default - %d : " % (1) , 1)
|
||||||
|
|
||||||
self.use_predicted_mask = io.input_bool("Use predicted mask? (y/n skip:y) : ", True)
|
if self.mask_mode == 3 or self.mask_mode == 4:
|
||||||
|
self.fan_seg = None
|
||||||
|
|
||||||
if self.mode != 'raw':
|
if self.mode != 'raw':
|
||||||
self.erode_mask_modifier = base_erode_mask_modifier + np.clip ( io.input_int ("Choose erode mask modifier [-200..200] (skip:%d) : " % (default_erode_mask_modifier), default_erode_mask_modifier), -200, 200)
|
self.erode_mask_modifier = base_erode_mask_modifier + np.clip ( io.input_int ("Choose erode mask modifier [-200..200] (skip:%d) : " % (default_erode_mask_modifier), default_erode_mask_modifier), -200, 200)
|
||||||
self.blur_mask_modifier = base_blur_mask_modifier + np.clip ( io.input_int ("Choose blur mask modifier [-200..200] (skip:%d) : " % (default_blur_mask_modifier), default_blur_mask_modifier), -200, 200)
|
self.blur_mask_modifier = base_blur_mask_modifier + np.clip ( io.input_int ("Choose blur mask modifier [-200..200] (skip:%d) : " % (default_blur_mask_modifier), default_blur_mask_modifier), -200, 200)
|
||||||
|
@ -93,7 +100,9 @@ class ConverterMasked(Converter):
|
||||||
|
|
||||||
#override
|
#override
|
||||||
def convert_face (self, img_bgr, img_face_landmarks, debug):
|
def convert_face (self, img_bgr, img_face_landmarks, debug):
|
||||||
|
if (self.mask_mode == 3 or self.mask_mode == 4) and self.fan_seg == None:
|
||||||
|
self.fan_seg = FANSegmentator(256, FaceType.toString(FaceType.FULL) )
|
||||||
|
|
||||||
if self.over_res != 1:
|
if self.over_res != 1:
|
||||||
img_bgr = cv2.resize ( img_bgr, ( img_bgr.shape[1]*self.over_res, img_bgr.shape[0]*self.over_res ) )
|
img_bgr = cv2.resize ( img_bgr, ( img_bgr.shape[1]*self.over_res, img_bgr.shape[0]*self.over_res ) )
|
||||||
img_face_landmarks = img_face_landmarks*self.over_res
|
img_face_landmarks = img_face_landmarks*self.over_res
|
||||||
|
@ -120,9 +129,18 @@ class ConverterMasked(Converter):
|
||||||
prd_face_bgr = np.clip (predicted_bgra[:,:,0:3], 0, 1.0 )
|
prd_face_bgr = np.clip (predicted_bgra[:,:,0:3], 0, 1.0 )
|
||||||
prd_face_mask_a_0 = np.clip (predicted_bgra[:,:,3], 0.0, 1.0)
|
prd_face_mask_a_0 = np.clip (predicted_bgra[:,:,3], 0.0, 1.0)
|
||||||
|
|
||||||
if not self.use_predicted_mask:
|
if self.mask_mode == 2: #dst
|
||||||
prd_face_mask_a_0 = predictor_input_mask_a_0
|
prd_face_mask_a_0 = predictor_input_mask_a_0
|
||||||
|
elif self.mask_mode == 3: #FAN-prd
|
||||||
|
prd_face_bgr_256 = cv2.resize (prd_face_bgr, (256,256) )
|
||||||
|
prd_face_bgr_256_mask = self.fan_seg.extract_from_bgr( np.expand_dims(prd_face_bgr_256,0) ) [0]
|
||||||
|
prd_face_mask_a_0 = cv2.resize (prd_face_bgr_256_mask, (self.predictor_input_size, self.predictor_input_size))
|
||||||
|
elif self.mask_mode == 4: #FAN-dst
|
||||||
|
face_256_mat = LandmarksProcessor.get_transform_mat (img_face_landmarks, 256, face_type=FaceType.FULL)
|
||||||
|
dst_face_256_bgr = cv2.warpAffine(img_bgr, face_256_mat, (256, 256), flags=cv2.INTER_LANCZOS4 )
|
||||||
|
dst_face_256_mask = self.fan_seg.extract_from_bgr( np.expand_dims(dst_face_256_bgr,0) ) [0]
|
||||||
|
prd_face_mask_a_0 = cv2.resize (dst_face_256_mask, (self.predictor_input_size, self.predictor_input_size))
|
||||||
|
|
||||||
prd_face_mask_a_0[ prd_face_mask_a_0 < 0.001 ] = 0.0
|
prd_face_mask_a_0[ prd_face_mask_a_0 < 0.001 ] = 0.0
|
||||||
|
|
||||||
prd_face_mask_a = np.expand_dims (prd_face_mask_a_0, axis=-1)
|
prd_face_mask_a = np.expand_dims (prd_face_mask_a_0, axis=-1)
|
||||||
|
|
Binary file not shown.
22563
doc/manual_ru_source.xml
22563
doc/manual_ru_source.xml
File diff suppressed because one or more lines are too long
BIN
facelib/FANSeg_256_full_face.h5
Normal file
BIN
facelib/FANSeg_256_full_face.h5
Normal file
Binary file not shown.
|
@ -8,16 +8,16 @@ from interact import interact as io
|
||||||
class FANSegmentator(object):
|
class FANSegmentator(object):
|
||||||
def __init__ (self, resolution, face_type_str, load_weights=True, weights_file_root=None, training=False):
|
def __init__ (self, resolution, face_type_str, load_weights=True, weights_file_root=None, training=False):
|
||||||
exec( nnlib.import_all(), locals(), globals() )
|
exec( nnlib.import_all(), locals(), globals() )
|
||||||
|
|
||||||
self.model = FANSegmentator.BuildModel(resolution, ngf=32)
|
self.model = FANSegmentator.BuildModel(resolution, ngf=32)
|
||||||
|
|
||||||
if weights_file_root:
|
if weights_file_root:
|
||||||
weights_file_root = Path(weights_file_root)
|
weights_file_root = Path(weights_file_root)
|
||||||
else:
|
else:
|
||||||
weights_file_root = Path(__file__).parent
|
weights_file_root = Path(__file__).parent
|
||||||
|
|
||||||
self.weights_path = weights_file_root / ('FANSeg_%d_%s.h5' % (resolution, face_type_str) )
|
self.weights_path = weights_file_root / ('FANSeg_%d_%s.h5' % (resolution, face_type_str) )
|
||||||
|
|
||||||
if load_weights:
|
if load_weights:
|
||||||
self.model.load_weights (str(self.weights_path))
|
self.model.load_weights (str(self.weights_path))
|
||||||
else:
|
else:
|
||||||
|
@ -33,19 +33,19 @@ class FANSegmentator(object):
|
||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def __exit__(self, exc_type=None, exc_value=None, traceback=None):
|
def __exit__(self, exc_type=None, exc_value=None, traceback=None):
|
||||||
return False #pass exception between __enter__ and __exit__ to outter level
|
return False #pass exception between __enter__ and __exit__ to outter level
|
||||||
|
|
||||||
def save_weights(self):
|
def save_weights(self):
|
||||||
self.model.save_weights (str(self.weights_path))
|
self.model.save_weights (str(self.weights_path))
|
||||||
|
|
||||||
def train_on_batch(self, inp, outp):
|
def train_on_batch(self, inp, outp):
|
||||||
return self.model.train_on_batch(inp, outp)
|
return self.model.train_on_batch(inp, outp)
|
||||||
|
|
||||||
def extract_from_bgr (self, input_image):
|
def extract_from_bgr (self, input_image):
|
||||||
return np.clip ( (self.model.predict(input_image) + 1) / 2.0, 0, 1.0 )
|
return np.clip ( (self.model.predict(input_image) + 1) / 2.0, 0, 1.0 )
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def BuildModel ( resolution, ngf=64):
|
def BuildModel ( resolution, ngf=64):
|
||||||
exec( nnlib.import_all(), locals(), globals() )
|
exec( nnlib.import_all(), locals(), globals() )
|
||||||
|
@ -55,7 +55,7 @@ class FANSegmentator(object):
|
||||||
x = FANSegmentator.DecFlow(ngf=ngf)(x)
|
x = FANSegmentator.DecFlow(ngf=ngf)(x)
|
||||||
model = Model(inp,x)
|
model = Model(inp,x)
|
||||||
return model
|
return model
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def EncFlow(ngf=64, num_downs=4):
|
def EncFlow(ngf=64, num_downs=4):
|
||||||
exec( nnlib.import_all(), locals(), globals() )
|
exec( nnlib.import_all(), locals(), globals() )
|
||||||
|
@ -67,19 +67,19 @@ class FANSegmentator(object):
|
||||||
def downscale (dim):
|
def downscale (dim):
|
||||||
def func(x):
|
def func(x):
|
||||||
return LeakyReLU(0.1)(XNormalization(Conv2D(dim, kernel_size=5, strides=2, padding='same', kernel_initializer=RandomNormal(0, 0.02))(x)))
|
return LeakyReLU(0.1)(XNormalization(Conv2D(dim, kernel_size=5, strides=2, padding='same', kernel_initializer=RandomNormal(0, 0.02))(x)))
|
||||||
return func
|
return func
|
||||||
|
|
||||||
def func(input):
|
def func(input):
|
||||||
x = input
|
x = input
|
||||||
|
|
||||||
result = []
|
result = []
|
||||||
for i in range(num_downs):
|
for i in range(num_downs):
|
||||||
x = downscale ( min(ngf*(2**i), ngf*8) )(x)
|
x = downscale ( min(ngf*(2**i), ngf*8) )(x)
|
||||||
result += [x]
|
result += [x]
|
||||||
|
|
||||||
return result
|
return result
|
||||||
return func
|
return func
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def DecFlow(output_nc=1, ngf=64, activation='tanh'):
|
def DecFlow(output_nc=1, ngf=64, activation='tanh'):
|
||||||
exec (nnlib.import_all(), locals(), globals())
|
exec (nnlib.import_all(), locals(), globals())
|
||||||
|
@ -87,23 +87,22 @@ class FANSegmentator(object):
|
||||||
use_bias = True
|
use_bias = True
|
||||||
def XNormalization(x):
|
def XNormalization(x):
|
||||||
return InstanceNormalization (axis=3, gamma_initializer=RandomNormal(1., 0.02))(x)
|
return InstanceNormalization (axis=3, gamma_initializer=RandomNormal(1., 0.02))(x)
|
||||||
|
|
||||||
def Conv2D (filters, kernel_size, strides=(1, 1), padding='valid', data_format=None, dilation_rate=(1, 1), activation=None, use_bias=use_bias, kernel_initializer=RandomNormal(0, 0.02), bias_initializer='zeros', kernel_regularizer=None, bias_regularizer=None, activity_regularizer=None, kernel_constraint=None, bias_constraint=None):
|
def Conv2D (filters, kernel_size, strides=(1, 1), padding='valid', data_format=None, dilation_rate=(1, 1), activation=None, use_bias=use_bias, kernel_initializer=RandomNormal(0, 0.02), bias_initializer='zeros', kernel_regularizer=None, bias_regularizer=None, activity_regularizer=None, kernel_constraint=None, bias_constraint=None):
|
||||||
return keras.layers.Conv2D( filters=filters, kernel_size=kernel_size, strides=strides, padding=padding, data_format=data_format, dilation_rate=dilation_rate, activation=activation, use_bias=use_bias, kernel_initializer=kernel_initializer, bias_initializer=bias_initializer, kernel_regularizer=kernel_regularizer, bias_regularizer=bias_regularizer, activity_regularizer=activity_regularizer, kernel_constraint=kernel_constraint, bias_constraint=bias_constraint )
|
return keras.layers.Conv2D( filters=filters, kernel_size=kernel_size, strides=strides, padding=padding, data_format=data_format, dilation_rate=dilation_rate, activation=activation, use_bias=use_bias, kernel_initializer=kernel_initializer, bias_initializer=bias_initializer, kernel_regularizer=kernel_regularizer, bias_regularizer=bias_regularizer, activity_regularizer=activity_regularizer, kernel_constraint=kernel_constraint, bias_constraint=bias_constraint )
|
||||||
|
|
||||||
def upscale (dim):
|
def upscale (dim):
|
||||||
def func(x):
|
def func(x):
|
||||||
return SubpixelUpscaler()( LeakyReLU(0.1)(XNormalization(Conv2D(dim, kernel_size=3, strides=1, padding='same', kernel_initializer=RandomNormal(0, 0.02))(x))))
|
return SubpixelUpscaler()( LeakyReLU(0.1)(XNormalization(Conv2D(dim, kernel_size=3, strides=1, padding='same', kernel_initializer=RandomNormal(0, 0.02))(x))))
|
||||||
return func
|
return func
|
||||||
|
|
||||||
def func(input):
|
def func(input):
|
||||||
input_len = len(input)
|
input_len = len(input)
|
||||||
|
|
||||||
x = input[input_len-1]
|
x = input[input_len-1]
|
||||||
for i in range(input_len-1, -1, -1):
|
for i in range(input_len-1, -1, -1):
|
||||||
x = upscale( min(ngf* (2**i) *4, ngf*8 *4 ) )(x)
|
x = upscale( min(ngf* (2**i) *4, ngf*8 *4 ) )(x)
|
||||||
if i != 0:
|
if i != 0:
|
||||||
x = Concatenate(axis=3)([ input[i-1] , x])
|
x = Concatenate(axis=3)([ input[i-1] , x])
|
||||||
|
|
||||||
return Conv2D(output_nc, 3, 1, 'same', activation=activation)(x)
|
return Conv2D(output_nc, 3, 1, 'same', activation=activation)(x)
|
||||||
return func
|
return func
|
Loading…
Add table
Add a link
Reference in a new issue