Merge remote-tracking branch 'upstream/master'

This commit is contained in:
sinofis 2021-01-09 15:19:28 +01:00
commit f69cfd2c79
7 changed files with 97 additions and 67 deletions

View file

@ -41,6 +41,11 @@ DeepFaceLab is used by such popular youtube channels as
|![](doc/youtube_icon.png) [Futuring Machine](https://www.youtube.com/channel/UCC5BbFxqLQgfnWPhprmQLVg)|![](doc/youtube_icon.png) [RepresentUS](https://www.youtube.com/channel/UCRzgK52MmetD9aG8pDOID3g)| |![](doc/youtube_icon.png) [Futuring Machine](https://www.youtube.com/channel/UCC5BbFxqLQgfnWPhprmQLVg)|![](doc/youtube_icon.png) [RepresentUS](https://www.youtube.com/channel/UCRzgK52MmetD9aG8pDOID3g)|
|---|---| |---|---|
|![](doc/youtube_icon.png) [DeepFakeCreator](https://www.youtube.com/channel/UCkNFhcYNLQ5hr6A6lZ56mKA)|![](doc/youtube_icon.png) [DeepFaker](https://www.youtube.com/channel/UCkHecfDTcSazNZSKPEhtPVQ)|
|---|---|
</td></tr> </td></tr>
<tr><td colspan=2 align="center"> <tr><td colspan=2 align="center">
@ -140,12 +145,14 @@ DeepFaceLab is used by such popular youtube channels as
<tr><td colspan=2 align="center"> <tr><td colspan=2 align="center">
## Manipulate politicians speech ## Manipulate politicians lips
(requires a skill in video editors such as *Adobe After Effects* or *Davinci Resolve*) (voice replacement is not included!)
(also requires a skill in video editors such as *Adobe After Effects* or *Davinci Resolve*)
<img src="doc/political_speech1.jpg" align="center"> <img src="doc/political_speech1.jpg" align="center">
![](doc/youtube_icon.png) https://www.youtube.com/watch?v=2Z1oA3GYPaY ![](doc/youtube_icon.png) https://www.youtube.com/watch?v=rYKkQ3BOo_E
<img src="doc/political_speech2.jpg" align="center"> <img src="doc/political_speech2.jpg" align="center">
@ -192,7 +199,7 @@ Unfortunately, there is no "make everything ok" button in DeepFaceLab. You shoul
</td></tr> </td></tr>
<tr><td align="right"> <tr><td align="right">
<a href="https://tinyurl.com/yb6gw8hu">Windows (magnet link)</a> <a href="https://tinyurl.com/y8lntghz">Windows (magnet link)</a>
</td><td align="center">Last release. Use torrent client to download.</td></tr> </td><td align="center">Last release. Use torrent client to download.</td></tr>
<tr><td align="right"> <tr><td align="right">
@ -267,6 +274,11 @@ Unfortunately, there is no "make everything ok" button in DeepFaceLab. You shoul
</td></tr> </td></tr>
<tr><td align="right">
<a href="https://discord.gg/S2h7kPySQp">Discord channel (English / Русский)</a>
</td><td align="center"></td></tr>
<tr><td align="right"> <tr><td align="right">
<a href="https://www.reddit.com/r/RUdeepfakes/new/">reddit r/RUdeepfakes/</a> <a href="https://www.reddit.com/r/RUdeepfakes/new/">reddit r/RUdeepfakes/</a>
</td><td align="center">Постим русские дипфейки сюда !</td></tr> </td><td align="center">Постим русские дипфейки сюда !</td></tr>
@ -288,7 +300,7 @@ Unfortunately, there is no "make everything ok" button in DeepFaceLab. You shoul
</td><td align="center">the biggest NSFW English community</td></tr> </td><td align="center">the biggest NSFW English community</td></tr>
<tr><td align="right"> <tr><td align="right">
<a href="https://www.reddit.com/r/SFWdeepfakes/new/">reddit r/SFWdeepfakes/</a> <a href="https://www.reddit.com/r/DeepFakesSFW/new/">reddit r/DeepFakesSFW/</a>
</td><td align="center">Post your deepfakes there !</td></tr> </td><td align="center">Post your deepfakes there !</td></tr>
<tr><td align="right"> <tr><td align="right">

View file

@ -94,7 +94,7 @@ class UNetPatchDiscriminator(nn.ModelBase):
ts *= s ts *= s
return rf return rf
def find_archi(self, target_patch_size, max_layers=6): def find_archi(self, target_patch_size, max_layers=9):
""" """
Find the best configuration of layers using only 3x3 convs for target patch size Find the best configuration of layers using only 3x3 convs for target patch size
""" """
@ -106,12 +106,12 @@ class UNetPatchDiscriminator(nn.ModelBase):
layers = [] layers = []
sum_st = 0 sum_st = 0
layers.append ( [3, 2])
sum_st += 2
for i in range(layers_count-1): for i in range(layers_count-1):
st = 1 + (1 if val & (1 << i) !=0 else 0 ) st = 1 + (1 if val & (1 << i) !=0 else 0 )
layers.append ( [3, st ]) layers.append ( [3, st ])
sum_st += st sum_st += st
layers.append ( [3, 2])
sum_st += 2
rf = self.calc_receptive_field_size(layers) rf = self.calc_receptive_field_size(layers)
@ -130,7 +130,8 @@ class UNetPatchDiscriminator(nn.ModelBase):
q=x[np.abs(np.array(x)-target_patch_size).argmin()] q=x[np.abs(np.array(x)-target_patch_size).argmin()]
return s[q][2] return s[q][2]
def on_build(self, patch_size, in_ch): def on_build(self, patch_size, in_ch, base_ch = 16):
class ResidualBlock(nn.ModelBase): class ResidualBlock(nn.ModelBase):
def on_build(self, ch, kernel_size=3 ): def on_build(self, ch, kernel_size=3 ):
self.conv1 = nn.Conv2D( ch, ch, kernel_size=kernel_size, padding='SAME') self.conv1 = nn.Conv2D( ch, ch, kernel_size=kernel_size, padding='SAME')
@ -145,11 +146,12 @@ class UNetPatchDiscriminator(nn.ModelBase):
prev_ch = in_ch prev_ch = in_ch
self.convs = [] self.convs = []
self.res = [] self.res1 = []
self.res2 = []
self.upconvs = [] self.upconvs = []
self.upres = [] self.upres1 = []
self.upres2 = []
layers = self.find_archi(patch_size) layers = self.find_archi(patch_size)
base_ch = 16
level_chs = { i-1:v for i,v in enumerate([ min( base_ch * (2**i), 512 ) for i in range(len(layers)+1)]) } level_chs = { i-1:v for i,v in enumerate([ min( base_ch * (2**i), 512 ) for i in range(len(layers)+1)]) }
@ -158,11 +160,13 @@ class UNetPatchDiscriminator(nn.ModelBase):
for i, (kernel_size, strides) in enumerate(layers): for i, (kernel_size, strides) in enumerate(layers):
self.convs.append ( nn.Conv2D( level_chs[i-1], level_chs[i], kernel_size=kernel_size, strides=strides, padding='SAME') ) self.convs.append ( nn.Conv2D( level_chs[i-1], level_chs[i], kernel_size=kernel_size, strides=strides, padding='SAME') )
self.res.append ( ResidualBlock(level_chs[i]) ) self.res1.append ( ResidualBlock(level_chs[i]) )
self.res2.append ( ResidualBlock(level_chs[i]) )
self.upconvs.insert (0, nn.Conv2DTranspose( level_chs[i]*(2 if i != len(layers)-1 else 1), level_chs[i-1], kernel_size=kernel_size, strides=strides, padding='SAME') ) self.upconvs.insert (0, nn.Conv2DTranspose( level_chs[i]*(2 if i != len(layers)-1 else 1), level_chs[i-1], kernel_size=kernel_size, strides=strides, padding='SAME') )
self.upres.insert (0, ResidualBlock(level_chs[i-1]*2) ) self.upres1.insert (0, ResidualBlock(level_chs[i-1]*2) )
self.upres2.insert (0, ResidualBlock(level_chs[i-1]*2) )
self.out_conv = nn.Conv2D( level_chs[-1]*2, 1, kernel_size=1, padding='VALID') self.out_conv = nn.Conv2D( level_chs[-1]*2, 1, kernel_size=1, padding='VALID')
@ -171,20 +175,22 @@ class UNetPatchDiscriminator(nn.ModelBase):
def forward(self, x): def forward(self, x):
x = tf.nn.leaky_relu( self.in_conv(x), 0.1 ) x = tf.nn.leaky_relu( self.in_conv(x), 0.2 )
encs = [] encs = []
for conv, res in zip(self.convs, self.res): for conv, res1,res2 in zip(self.convs, self.res1, self.res2):
encs.insert(0, x) encs.insert(0, x)
x = tf.nn.leaky_relu( conv(x), 0.1 ) x = tf.nn.leaky_relu( conv(x), 0.2 )
x = res(x) x = res1(x)
x = res2(x)
center_out, x = self.center_out(x), self.center_conv(x) center_out, x = self.center_out(x), tf.nn.leaky_relu( self.center_conv(x), 0.2 )
for i, (upconv, enc, upres) in enumerate(zip(self.upconvs, encs, self.upres)): for i, (upconv, enc, upres1, upres2 ) in enumerate(zip(self.upconvs, encs, self.upres1, self.upres2)):
x = tf.nn.leaky_relu( upconv(x), 0.1 ) x = tf.nn.leaky_relu( upconv(x), 0.2 )
x = tf.concat( [enc, x], axis=nn.conv2d_ch_axis) x = tf.concat( [enc, x], axis=nn.conv2d_ch_axis)
x = upres(x) x = upres1(x)
x = upres2(x)
return center_out, self.out_conv(x) return center_out, self.out_conv(x)

View file

@ -76,14 +76,25 @@ class nn():
if first_run: if first_run:
io.log_info("Caching GPU kernels...") io.log_info("Caching GPU kernels...")
#import tensorflow as tf import tensorflow
import tensorflow.compat.v1 as tf
tf_version = getattr(tensorflow,'VERSION', None)
if tf_version is None:
tf_version = tensorflow.version.GIT_VERSION
if tf_version[0] == 'v':
tf_version = tf_version[1:]
if tf_version[0] == '2':
tf = tensorflow.compat.v1
else:
tf = tensorflow
import logging import logging
# Disable tensorflow warnings # Disable tensorflow warnings
tf_logger = logging.getLogger('tensorflow') tf_logger = logging.getLogger('tensorflow')
tf_logger.setLevel(logging.ERROR) tf_logger.setLevel(logging.ERROR)
if tf_version[0] == '2':
tf.disable_v2_behavior() tf.disable_v2_behavior()
nn.tf = tf nn.tf = tf

Binary file not shown.

Before

Width:  |  Height:  |  Size: 548 KiB

After

Width:  |  Height:  |  Size: 247 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 310 KiB

After

Width:  |  Height:  |  Size: 260 KiB

Before After
Before After

View file

@ -139,6 +139,10 @@ Examples: df, liae, df-d, df-ud, liae-ud, ...
self.options['uniform_yaw'] = io.input_bool ("Uniform yaw distribution of samples", default_uniform_yaw, help_message='Helps to fix blurry side faces due to small amount of them in the faceset.') self.options['uniform_yaw'] = io.input_bool ("Uniform yaw distribution of samples", default_uniform_yaw, help_message='Helps to fix blurry side faces due to small amount of them in the faceset.')
default_gan_power = self.options['gan_power'] = self.load_or_def_option('gan_power', 0.0)
default_gan_patch_size = self.options['gan_patch_size'] = self.load_or_def_option('gan_patch_size', self.options['resolution'] // 8)
default_gan_dims = self.options['gan_dims'] = self.load_or_def_option('gan_dims', 16)
if self.is_first_run() or ask_override: if self.is_first_run() or ask_override:
self.options['models_opt_on_gpu'] = io.input_bool ("Place models and optimizer on GPU", default_models_opt_on_gpu, help_message="When you train on one GPU, by default model and optimizer weights are placed on GPU to accelerate the process. You can place they on CPU to free up extra VRAM, thus set bigger dimensions.") self.options['models_opt_on_gpu'] = io.input_bool ("Place models and optimizer on GPU", default_models_opt_on_gpu, help_message="When you train on one GPU, by default model and optimizer weights are placed on GPU to accelerate the process. You can place they on CPU to free up extra VRAM, thus set bigger dimensions.")
@ -148,10 +152,14 @@ Examples: df, liae, df-d, df-ud, liae-ud, ...
self.options['random_warp'] = io.input_bool ("Enable random warp of samples", default_random_warp, help_message="Random warp is required to generalize facial expressions of both faces. When the face is trained enough, you can disable it to get extra sharpness and reduce subpixel shake for less amount of iterations.") self.options['random_warp'] = io.input_bool ("Enable random warp of samples", default_random_warp, help_message="Random warp is required to generalize facial expressions of both faces. When the face is trained enough, you can disable it to get extra sharpness and reduce subpixel shake for less amount of iterations.")
self.options['gan_power'] = np.clip ( io.input_number ("GAN power", default_gan_power, add_info="0.0 .. 10.0", help_message="Train the network in Generative Adversarial manner. Forces the neural network to learn small details of the face. Enable it only when the face is trained enough and don't disable. Typical fine value is 0.05"), 0.0, 10.0 ) self.options['gan_power'] = np.clip ( io.input_number ("GAN power", default_gan_power, add_info="0.0 .. 1.0", help_message="Forces the neural network to learn small details of the face. Enable it only when the face is trained enough with lr_dropout(on) and random_warp(off), and don't disable. The higher the value, the higher the chances of artifacts. Typical fine value is 0.1"), 0.0, 1.0 )
if (self.options['gan_power'] != 0): if self.options['gan_power'] != 0.0:
self.options['gan_old'] = io.input_bool ("Use old GAN version", default_gan_old, help_message="Use older version of GAN." ) gan_patch_size = np.clip ( io.input_int("GAN patch size", default_gan_patch_size, add_info="3-640", help_message="The higher patch size, the higher the quality, the more VRAM is required. You can get sharper edges even at the lowest setting. Typical fine value is resolution / 8." ), 3, 640 )
self.options['gan_patch_size'] = gan_patch_size
gan_dims = np.clip ( io.input_int("GAN dimensions", default_gan_dims, add_info="4-64", help_message="The dimensions of the GAN network. The higher dimensions, the more VRAM is required. You can get sharper edges even at the lowest setting. Typical fine value is 16." ), 4, 64 )
self.options['gan_dims'] = gan_dims
if 'df' in self.options['archi']: if 'df' in self.options['archi']:
self.options['true_face_power'] = np.clip ( io.input_number ("'True face' power.", default_true_face_power, add_info="0.0000 .. 1.0", help_message="Experimental option. Discriminates result face to be more like src face. Higher value - stronger discrimination. Typical value is 0.01 . Comparison - https://i.imgur.com/czScS9q.png"), 0.0, 1.0 ) self.options['true_face_power'] = np.clip ( io.input_number ("'True face' power.", default_true_face_power, add_info="0.0000 .. 1.0", help_message="Experimental option. Discriminates result face to be more like src face. Higher value - stronger discrimination. Typical value is 0.01 . Comparison - https://i.imgur.com/czScS9q.png"), 0.0, 1.0 )
@ -169,6 +177,8 @@ Examples: df, liae, df-d, df-ud, liae-ud, ...
if self.options['pretrain'] and self.get_pretraining_data_path() is None: if self.options['pretrain'] and self.get_pretraining_data_path() is None:
raise Exception("pretraining_data_path is not defined") raise Exception("pretraining_data_path is not defined")
self.gan_model_changed = (default_gan_patch_size != self.options['gan_patch_size']) or (default_gan_dims != self.options['gan_dims'])
self.pretrain_just_disabled = (default_pretrain == True and self.options['pretrain'] == False) self.pretrain_just_disabled = (default_pretrain == True and self.options['pretrain'] == False)
#override #override
@ -289,14 +299,8 @@ Examples: df, liae, df-d, df-ud, liae-ud, ...
if self.is_training: if self.is_training:
if gan_power != 0: if gan_power != 0:
if gan_old: self.D_src = nn.UNetPatchDiscriminator(patch_size=self.options['gan_patch_size'], in_ch=input_ch, base_ch=self.options['gan_dims'], name="D_src")
self.D_src = nn.PatchDiscriminator(patch_size=resolution//16, in_ch=input_ch, name="D_src") self.model_filename_list += [ [self.D_src, 'GAN.npy'] ]
self.D_src_x2 = nn.PatchDiscriminator(patch_size=resolution//32, in_ch=input_ch, name="D_src_x2")
self.model_filename_list += [ [self.D_src, 'D_src.npy'] ]
self.model_filename_list += [ [self.D_src_x2, 'D_src_x2.npy'] ]
else:
self.D_src = nn.UNetPatchDiscriminator(patch_size=resolution//16, in_ch=input_ch, name="D_src")
self.model_filename_list += [ [self.D_src, 'D_src_v2.npy'] ]
# Initialize optimizers # Initialize optimizers
lr=5e-5 lr=5e-5
@ -321,14 +325,9 @@ Examples: df, liae, df-d, df-ud, liae-ud, ...
self.model_filename_list += [ (self.D_code_opt, 'D_code_opt.npy') ] self.model_filename_list += [ (self.D_code_opt, 'D_code_opt.npy') ]
if gan_power != 0: if gan_power != 0:
self.D_src_dst_opt = OptimizerClass(lr=lr, lr_dropout=lr_dropout, clipnorm=clipnorm, name='D_src_dst_opt') self.D_src_dst_opt = OptimizerClass(lr=lr, lr_dropout=lr_dropout, clipnorm=clipnorm, name='GAN_opt')
if gan_old:
self.D_src_dst_opt.initialize_variables ( self.D_src.get_weights()+self.D_src_x2.get_weights(), vars_on_cpu=optimizer_vars_on_cpu, lr_dropout_on_cpu=self.options['lr_dropout']=='cpu')
self.model_filename_list += [ (self.D_src_dst_opt, 'D_src_dst_opt.npy') ]
else:
self.D_src_dst_opt.initialize_variables ( self.D_src.get_weights(), vars_on_cpu=optimizer_vars_on_cpu, lr_dropout_on_cpu=self.options['lr_dropout']=='cpu')#+self.D_src_x2.get_weights() self.D_src_dst_opt.initialize_variables ( self.D_src.get_weights(), vars_on_cpu=optimizer_vars_on_cpu, lr_dropout_on_cpu=self.options['lr_dropout']=='cpu')#+self.D_src_x2.get_weights()
self.model_filename_list += [ (self.D_src_dst_opt, 'D_src_v2_opt.npy') ] self.model_filename_list += [ (self.D_src_dst_opt, 'GAN_opt.npy') ]
if self.is_training: if self.is_training:
# Adjust batch size for multiple GPU # Adjust batch size for multiple GPU
@ -416,10 +415,12 @@ Examples: df, liae, df-d, df-ud, liae-ud, ...
gpu_target_dst_style_masked = gpu_target_dst*gpu_target_dstm_style_blur gpu_target_dst_style_masked = gpu_target_dst*gpu_target_dstm_style_blur
gpu_target_dst_style_anti_masked = gpu_target_dst*(1.0 - gpu_target_dstm_style_blur) gpu_target_dst_style_anti_masked = gpu_target_dst*(1.0 - gpu_target_dstm_style_blur)
gpu_target_src_anti_masked = gpu_target_src*(1.0-gpu_target_srcm_blur)
gpu_target_src_masked_opt = gpu_target_src*gpu_target_srcm_blur if masked_training else gpu_target_src gpu_target_src_masked_opt = gpu_target_src*gpu_target_srcm_blur if masked_training else gpu_target_src
gpu_target_dst_masked_opt = gpu_target_dst_masked if masked_training else gpu_target_dst gpu_target_dst_masked_opt = gpu_target_dst_masked if masked_training else gpu_target_dst
gpu_pred_src_src_masked_opt = gpu_pred_src_src*gpu_target_srcm_blur if masked_training else gpu_pred_src_src gpu_pred_src_src_masked_opt = gpu_pred_src_src*gpu_target_srcm_blur if masked_training else gpu_pred_src_src
gpu_pred_src_src_anti_masked = gpu_pred_src_src*(1.0-gpu_target_srcm_blur)
gpu_pred_dst_dst_masked_opt = gpu_pred_dst_dst*gpu_target_dstm_blur if masked_training else gpu_pred_dst_dst gpu_pred_dst_dst_masked_opt = gpu_pred_dst_dst*gpu_target_dstm_blur if masked_training else gpu_pred_dst_dst
gpu_psd_target_dst_style_masked = gpu_pred_src_dst*gpu_target_dstm_style_blur gpu_psd_target_dst_style_masked = gpu_pred_src_dst*gpu_target_dstm_style_blur
@ -533,19 +534,16 @@ Examples: df, liae, df-d, df-ud, liae-ud, ...
gpu_target_src_d, \ gpu_target_src_d, \
gpu_target_src_d2 = self.D_src(gpu_target_src_masked_opt) gpu_target_src_d2 = self.D_src(gpu_target_src_masked_opt)
gpu_target_src_d_ones = tf.ones_like(gpu_target_src_d)
gpu_target_src_d2_ones = tf.ones_like(gpu_target_src_d2)
gpu_D_src_dst_loss = (DLoss(gpu_target_src_d_ones , gpu_target_src_d) + \
DLoss(gpu_pred_src_src_d_zeros , gpu_pred_src_src_d) ) * 0.5 + \
(DLoss(gpu_target_src_d2_ones , gpu_target_src_d2) + \
DLoss(gpu_pred_src_src_d2_zeros , gpu_pred_src_src_d2) ) * 0.5
gpu_D_src_dst_loss_gvs += [ nn.gradients (gpu_D_src_dst_loss, self.D_src.get_weights() ) ]#+self.D_src_x2.get_weights()
gpu_G_loss += gan_power*(DLoss(gpu_pred_src_src_d_ones, gpu_pred_src_src_d) + \ gpu_G_loss += gan_power*(DLoss(gpu_pred_src_src_d_ones, gpu_pred_src_src_d) + \
DLoss(gpu_pred_src_src_d2_ones, gpu_pred_src_src_d2)) DLoss(gpu_pred_src_src_d2_ones, gpu_pred_src_src_d2))
if masked_training:
# Minimal src-src-bg rec with total_variation_mse to suppress random bright dots from gan
gpu_G_loss += 0.000001*nn.total_variation_mse(gpu_pred_src_src)
gpu_G_loss += 0.02*tf.reduce_mean(tf.square(gpu_pred_src_src_anti_masked-gpu_target_src_anti_masked),axis=[1,2,3] )
gpu_G_loss_gvs += [ nn.gradients ( gpu_G_loss, self.src_dst_trainable_weights ) ] gpu_G_loss_gvs += [ nn.gradients ( gpu_G_loss, self.src_dst_trainable_weights ) ]
@ -646,6 +644,9 @@ Examples: df, liae, df-d, df-ud, liae-ud, ...
do_init = True do_init = True
else: else:
do_init = self.is_first_run() do_init = self.is_first_run()
if self.is_training and gan_power != 0 and model == self.D_src:
if self.gan_model_changed:
do_init = True
if not do_init: if not do_init:
do_init = not model.load_weights( self.get_strpath_storage_for_file(filename) ) do_init = not model.load_weights( self.get_strpath_storage_for_file(filename) )