mirror of
https://github.com/iperov/DeepFaceLab.git
synced 2025-08-14 02:37:00 -07:00
Upgraded to TF version 1.13.2
Removed the wait at first launch for most graphics cards. Increased speed of training by 10-20%, but you have to retrain all models from scratch. SAEHD: added option 'use float16' Experimental option. Reduces the model size by half. Increases the speed of training. Decreases the accuracy of the model. The model may collapse or not train. Model may not learn the mask in large resolutions. true_face_training option is replaced by "True face power". 0.0000 .. 1.0 Experimental option. Discriminates the result face to be more like the src face. Higher value - stronger discrimination. Comparison - https://i.imgur.com/czScS9q.png
This commit is contained in:
parent
a3dfcb91b9
commit
76ca79216e
49 changed files with 1320 additions and 1297 deletions
|
@ -18,7 +18,7 @@ class FANExtractor(object):
|
|||
if not model_path.exists():
|
||||
raise Exception("Unable to load FANExtractor model")
|
||||
|
||||
nn.initialize()
|
||||
nn.initialize(data_format="NHWC")
|
||||
tf = nn.tf
|
||||
|
||||
class ConvBlock(nn.ModelBase):
|
||||
|
@ -29,10 +29,10 @@ class FANExtractor(object):
|
|||
self.bn1 = nn.BatchNorm2D(in_planes)
|
||||
self.conv1 = nn.Conv2D (in_planes, out_planes/2, kernel_size=3, strides=1, padding='SAME', use_bias=False )
|
||||
|
||||
self.bn2 = nn.BatchNorm2D(out_planes/2)
|
||||
self.bn2 = nn.BatchNorm2D(out_planes//2)
|
||||
self.conv2 = nn.Conv2D (out_planes/2, out_planes/4, kernel_size=3, strides=1, padding='SAME', use_bias=False )
|
||||
|
||||
self.bn3 = nn.BatchNorm2D(out_planes/4)
|
||||
self.bn3 = nn.BatchNorm2D(out_planes//4)
|
||||
self.conv3 = nn.Conv2D (out_planes/4, out_planes/4, kernel_size=3, strides=1, padding='SAME', use_bias=False )
|
||||
|
||||
if self.in_planes != self.out_planes:
|
||||
|
@ -55,6 +55,7 @@ class FANExtractor(object):
|
|||
x = self.bn3(x)
|
||||
x = tf.nn.relu(x)
|
||||
x = out3 = self.conv3(x)
|
||||
|
||||
x = tf.concat ([out1, out2, out3], axis=-1)
|
||||
|
||||
if self.in_planes != self.out_planes:
|
||||
|
@ -148,7 +149,9 @@ class FANExtractor(object):
|
|||
if i < 4 - 1:
|
||||
ll = self.bl[i](ll)
|
||||
previous = previous + ll + self.al[i](tmp_out)
|
||||
return outputs[-1]
|
||||
x = outputs[-1]
|
||||
x = tf.transpose(x, (0,3,1,2) )
|
||||
return x
|
||||
|
||||
e = None
|
||||
if place_model_on_cpu:
|
||||
|
@ -159,7 +162,7 @@ class FANExtractor(object):
|
|||
self.model.load_weights(str(model_path))
|
||||
if e is not None: e.__exit__(None,None,None)
|
||||
|
||||
self.model.build_for_run ([ ( tf.float32, (256,256,3) ) ])
|
||||
self.model.build_for_run ([ ( tf.float32, (None,256,256,3) ) ])
|
||||
|
||||
def extract (self, input_image, rects, second_pass_extractor=None, is_bgr=True, multi_sample=False):
|
||||
if len(rects) == 0:
|
||||
|
@ -197,7 +200,7 @@ class FANExtractor(object):
|
|||
|
||||
predicted = []
|
||||
for i in range( len(images) ):
|
||||
predicted += [ self.model.run ( [ images[i][None,...] ] ).transpose (0,3,1,2)[0] ]
|
||||
predicted += [ self.model.run ( [ images[i][None,...] ] )[0] ]
|
||||
|
||||
predicted = np.stack(predicted)
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ class FaceEnhancer(object):
|
|||
x4 face enhancer
|
||||
"""
|
||||
def __init__(self, place_model_on_cpu=False):
|
||||
nn.initialize()
|
||||
nn.initialize(data_format="NHWC")
|
||||
tf = nn.tf
|
||||
|
||||
class FaceEnhancer (nn.ModelBase):
|
||||
|
@ -167,9 +167,9 @@ class FaceEnhancer(object):
|
|||
self.model.load_weights (model_path)
|
||||
if e is not None: e.__exit__(None,None,None)
|
||||
|
||||
self.model.build_for_run ([ (tf.float32, (192,192,3) ),
|
||||
(tf.float32, (1,) ),
|
||||
(tf.float32, (1,) ),
|
||||
self.model.build_for_run ([ (tf.float32, nn.get4Dshape (192,192,3) ),
|
||||
(tf.float32, (None,1,) ),
|
||||
(tf.float32, (None,1,) ),
|
||||
])
|
||||
|
||||
|
||||
|
@ -185,14 +185,14 @@ class FaceEnhancer(object):
|
|||
|
||||
ih,iw,ic = inp_img.shape
|
||||
h,w,c = ih,iw,ic
|
||||
|
||||
|
||||
th,tw = h*up_res, w*up_res
|
||||
|
||||
|
||||
t_padding = 0
|
||||
b_padding = 0
|
||||
l_padding = 0
|
||||
r_padding = 0
|
||||
|
||||
|
||||
if h < patch_size:
|
||||
t_padding = (patch_size-h)//2
|
||||
b_padding = (patch_size-h) - t_padding
|
||||
|
@ -200,24 +200,24 @@ class FaceEnhancer(object):
|
|||
if w < patch_size:
|
||||
l_padding = (patch_size-w)//2
|
||||
r_padding = (patch_size-w) - l_padding
|
||||
|
||||
|
||||
if t_padding != 0:
|
||||
inp_img = np.concatenate ([ np.zeros ( (t_padding,w,c), dtype=np.float32 ), inp_img ], axis=0 )
|
||||
h,w,c = inp_img.shape
|
||||
|
||||
h,w,c = inp_img.shape
|
||||
|
||||
if b_padding != 0:
|
||||
inp_img = np.concatenate ([ inp_img, np.zeros ( (b_padding,w,c), dtype=np.float32 ) ], axis=0 )
|
||||
h,w,c = inp_img.shape
|
||||
|
||||
|
||||
if l_padding != 0:
|
||||
inp_img = np.concatenate ([ np.zeros ( (h,l_padding,c), dtype=np.float32 ), inp_img ], axis=1 )
|
||||
h,w,c = inp_img.shape
|
||||
|
||||
h,w,c = inp_img.shape
|
||||
|
||||
if r_padding != 0:
|
||||
inp_img = np.concatenate ([ inp_img, np.zeros ( (h,r_padding,c), dtype=np.float32 ) ], axis=1 )
|
||||
h,w,c = inp_img.shape
|
||||
|
||||
|
||||
|
||||
|
||||
i_max = w-patch_size+1
|
||||
j_max = h-patch_size+1
|
||||
|
||||
|
@ -248,7 +248,7 @@ class FaceEnhancer(object):
|
|||
|
||||
if t_padding+b_padding+l_padding+r_padding != 0:
|
||||
final_img = final_img [t_padding*up_res:(h-b_padding)*up_res, l_padding*up_res:(w-r_padding)*up_res,:]
|
||||
|
||||
|
||||
if preserve_size:
|
||||
final_img = cv2.resize (final_img, (iw,ih), cv2.INTER_LANCZOS4)
|
||||
|
||||
|
@ -271,15 +271,15 @@ class FaceEnhancer(object):
|
|||
patch_size_half = patch_size // 2
|
||||
|
||||
h,w,c = inp_img.shape
|
||||
|
||||
|
||||
th,tw = h*up_res, w*up_res
|
||||
|
||||
|
||||
preupscale_rate = 1.0
|
||||
|
||||
|
||||
if h < patch_size or w < patch_size:
|
||||
preupscale_rate = 1.0 / ( max(h,w) / patch_size )
|
||||
|
||||
if preupscale_rate != 1.0:
|
||||
|
||||
if preupscale_rate != 1.0:
|
||||
inp_img = cv2.resize (inp_img, ( int(w*preupscale_rate), int(h*preupscale_rate) ), cv2.INTER_LANCZOS4)
|
||||
h,w,c = inp_img.shape
|
||||
|
||||
|
@ -314,7 +314,7 @@ class FaceEnhancer(object):
|
|||
if preserve_size:
|
||||
final_img = cv2.resize (final_img, (w,h), cv2.INTER_LANCZOS4)
|
||||
else:
|
||||
if preupscale_rate != 1.0:
|
||||
if preupscale_rate != 1.0:
|
||||
final_img = cv2.resize (final_img, (tw,th), cv2.INTER_LANCZOS4)
|
||||
|
||||
if not is_tanh:
|
||||
|
|
|
@ -8,7 +8,7 @@ class FaceType(IntEnum):
|
|||
FULL_NO_ALIGN = 3
|
||||
HEAD = 4
|
||||
HEAD_NO_ALIGN = 5
|
||||
|
||||
|
||||
MARK_ONLY = 10, #no align at all, just embedded faceinfo
|
||||
|
||||
@staticmethod
|
||||
|
|
|
@ -263,29 +263,29 @@ def get_transform_mat (image_landmarks, output_size, face_type, scale=1.0, full_
|
|||
tb_diag_vec /= npla.norm(tb_diag_vec)
|
||||
bt_diag_vec = (l_p[1]-l_p[3]).astype(np.float32)
|
||||
bt_diag_vec /= npla.norm(bt_diag_vec)
|
||||
|
||||
|
||||
mod = (1.0 / scale)* ( npla.norm(l_p[0]-l_p[2])*(padding*np.sqrt(2.0) + 0.5) )
|
||||
|
||||
|
||||
if not remove_align:
|
||||
l_t = np.array( [ np.round( l_c - tb_diag_vec*mod ),
|
||||
np.round( l_c + bt_diag_vec*mod ),
|
||||
np.round( l_c + tb_diag_vec*mod ) ] )
|
||||
l_t = np.array( [ np.round( l_c - tb_diag_vec*mod ),
|
||||
np.round( l_c + bt_diag_vec*mod ),
|
||||
np.round( l_c + tb_diag_vec*mod ) ] )
|
||||
else:
|
||||
l_t = np.array( [ np.round( l_c - tb_diag_vec*mod ),
|
||||
np.round( l_c + bt_diag_vec*mod ),
|
||||
l_t = np.array( [ np.round( l_c - tb_diag_vec*mod ),
|
||||
np.round( l_c + bt_diag_vec*mod ),
|
||||
np.round( l_c + tb_diag_vec*mod ),
|
||||
np.round( l_c - bt_diag_vec*mod ),
|
||||
np.round( l_c - bt_diag_vec*mod ),
|
||||
] )
|
||||
|
||||
|
||||
area = mathlib.polygon_area(l_t[:,0], l_t[:,1] )
|
||||
side = np.float32(math.sqrt(area) / 2)
|
||||
l_t = np.array( [ np.round( l_c + [-side,-side] ),
|
||||
np.round( l_c + [ side,-side] ),
|
||||
np.round( l_c + [ side, side] ) ] )
|
||||
|
||||
l_t = np.array( [ np.round( l_c + [-side,-side] ),
|
||||
np.round( l_c + [ side,-side] ),
|
||||
np.round( l_c + [ side, side] ) ] )
|
||||
|
||||
pts2 = np.float32(( (0,0),(output_size,0),(output_size,output_size) ))
|
||||
mat = cv2.getAffineTransform(l_t,pts2)
|
||||
|
||||
|
||||
|
||||
#if remove_align:
|
||||
# bbox = transform_points ( [ (0,0), (0,output_size), (output_size, output_size), (output_size,0) ], mat, True)
|
||||
|
@ -301,24 +301,24 @@ def get_transform_mat (image_landmarks, output_size, face_type, scale=1.0, full_
|
|||
return mat
|
||||
|
||||
#if full_face_align_top and (face_type == FaceType.FULL or face_type == FaceType.FULL_NO_ALIGN):
|
||||
# #lmrks2 = expand_eyebrows(image_landmarks)
|
||||
# #lmrks2_ = transform_points( [ lmrks2[19], lmrks2[24] ], mat, False )
|
||||
# #y_diff = np.float32( (0,np.min(lmrks2_[:,1])) )
|
||||
# #lmrks2 = expand_eyebrows(image_landmarks)
|
||||
# #lmrks2_ = transform_points( [ lmrks2[19], lmrks2[24] ], mat, False )
|
||||
# #y_diff = np.float32( (0,np.min(lmrks2_[:,1])) )
|
||||
# #y_diff = transform_points( [ np.float32( (0,0) ), y_diff], mat, True)
|
||||
# #y_diff = y_diff[1]-y_diff[0]
|
||||
#
|
||||
#
|
||||
# x_diff = np.float32((0,0))
|
||||
#
|
||||
# lmrks2_ = transform_points( [ image_landmarks[0], image_landmarks[16] ], mat, False )
|
||||
#
|
||||
# lmrks2_ = transform_points( [ image_landmarks[0], image_landmarks[16] ], mat, False )
|
||||
# if lmrks2_[0,0] < 0:
|
||||
# x_diff = lmrks2_[0,0]
|
||||
# x_diff = lmrks2_[0,0]
|
||||
# x_diff = transform_points( [ np.float32( (0,0) ), np.float32((x_diff,0)) ], mat, True)
|
||||
# x_diff = x_diff[1]-x_diff[0]
|
||||
# x_diff = x_diff[1]-x_diff[0]
|
||||
# elif lmrks2_[1,0] >= output_size:
|
||||
# x_diff = lmrks2_[1,0]-(output_size-1)
|
||||
# x_diff = transform_points( [ np.float32( (0,0) ), np.float32((x_diff,0)) ], mat, True)
|
||||
# x_diff = x_diff[1]-x_diff[0]
|
||||
#
|
||||
# x_diff = x_diff[1]-x_diff[0]
|
||||
#
|
||||
# mat = cv2.getAffineTransform( l_t+y_diff+x_diff ,pts2)
|
||||
def expand_eyebrows(lmrks, eyebrows_expand_mod=1.0):
|
||||
if len(lmrks) != 68:
|
||||
|
@ -687,5 +687,5 @@ def estimate_pitch_yaw_roll(aligned_256px_landmarks):
|
|||
pitch = np.clip ( pitch, -math.pi, math.pi )
|
||||
yaw = np.clip ( yaw , -math.pi, math.pi )
|
||||
roll = np.clip ( roll, -math.pi, math.pi )
|
||||
|
||||
|
||||
return -pitch, yaw, roll
|
||||
|
|
|
@ -8,9 +8,9 @@ from core.leras import nn
|
|||
|
||||
class S3FDExtractor(object):
|
||||
def __init__(self, place_model_on_cpu=False):
|
||||
nn.initialize()
|
||||
nn.initialize(data_format="NHWC")
|
||||
tf = nn.tf
|
||||
|
||||
|
||||
model_path = Path(__file__).parent / "S3FD.npy"
|
||||
if not model_path.exists():
|
||||
raise Exception("Unable to load S3FD.npy")
|
||||
|
@ -19,143 +19,143 @@ class S3FDExtractor(object):
|
|||
def __init__(self, n_channels, **kwargs):
|
||||
self.n_channels = n_channels
|
||||
super().__init__(**kwargs)
|
||||
|
||||
|
||||
def build_weights(self):
|
||||
self.weight = tf.get_variable ("weight", (1, 1, 1, self.n_channels), dtype=nn.tf_floatx, initializer=tf.initializers.ones )
|
||||
|
||||
def get_weights(self):
|
||||
return [self.weight]
|
||||
|
||||
|
||||
def __call__(self, inputs):
|
||||
x = inputs
|
||||
x = x / (tf.sqrt( tf.reduce_sum( tf.pow(x, 2), axis=-1, keepdims=True ) ) + 1e-10) * self.weight
|
||||
return x
|
||||
|
||||
|
||||
class S3FD(nn.ModelBase):
|
||||
def __init__(self):
|
||||
super().__init__(name='S3FD')
|
||||
|
||||
|
||||
def on_build(self):
|
||||
self.minus = tf.constant([104,117,123], dtype=nn.tf_floatx )
|
||||
self.conv1_1 = nn.Conv2D(3, 64, kernel_size=3, strides=1, padding='SAME')
|
||||
self.conv1_2 = nn.Conv2D(64, 64, kernel_size=3, strides=1, padding='SAME')
|
||||
|
||||
|
||||
self.conv2_1 = nn.Conv2D(64, 128, kernel_size=3, strides=1, padding='SAME')
|
||||
self.conv2_2 = nn.Conv2D(128, 128, kernel_size=3, strides=1, padding='SAME')
|
||||
|
||||
|
||||
self.conv3_1 = nn.Conv2D(128, 256, kernel_size=3, strides=1, padding='SAME')
|
||||
self.conv3_2 = nn.Conv2D(256, 256, kernel_size=3, strides=1, padding='SAME')
|
||||
self.conv3_3 = nn.Conv2D(256, 256, kernel_size=3, strides=1, padding='SAME')
|
||||
|
||||
|
||||
self.conv4_1 = nn.Conv2D(256, 512, kernel_size=3, strides=1, padding='SAME')
|
||||
self.conv4_2 = nn.Conv2D(512, 512, kernel_size=3, strides=1, padding='SAME')
|
||||
self.conv4_3 = nn.Conv2D(512, 512, kernel_size=3, strides=1, padding='SAME')
|
||||
|
||||
|
||||
self.conv5_1 = nn.Conv2D(512, 512, kernel_size=3, strides=1, padding='SAME')
|
||||
self.conv5_2 = nn.Conv2D(512, 512, kernel_size=3, strides=1, padding='SAME')
|
||||
self.conv5_3 = nn.Conv2D(512, 512, kernel_size=3, strides=1, padding='SAME')
|
||||
|
||||
|
||||
self.fc6 = nn.Conv2D(512, 1024, kernel_size=3, strides=1, padding=3)
|
||||
self.fc7 = nn.Conv2D(1024, 1024, kernel_size=1, strides=1, padding='SAME')
|
||||
|
||||
|
||||
self.conv6_1 = nn.Conv2D(1024, 256, kernel_size=1, strides=1, padding='SAME')
|
||||
self.conv6_2 = nn.Conv2D(256, 512, kernel_size=3, strides=2, padding='SAME')
|
||||
|
||||
|
||||
self.conv7_1 = nn.Conv2D(512, 128, kernel_size=1, strides=1, padding='SAME')
|
||||
self.conv7_2 = nn.Conv2D(128, 256, kernel_size=3, strides=2, padding='SAME')
|
||||
|
||||
|
||||
self.conv3_3_norm = L2Norm(256)
|
||||
self.conv4_3_norm = L2Norm(512)
|
||||
self.conv5_3_norm = L2Norm(512)
|
||||
|
||||
|
||||
|
||||
|
||||
self.conv3_3_norm_mbox_conf = nn.Conv2D(256, 4, kernel_size=3, strides=1, padding='SAME')
|
||||
self.conv3_3_norm_mbox_loc = nn.Conv2D(256, 4, kernel_size=3, strides=1, padding='SAME')
|
||||
|
||||
|
||||
self.conv4_3_norm_mbox_conf = nn.Conv2D(512, 2, kernel_size=3, strides=1, padding='SAME')
|
||||
self.conv4_3_norm_mbox_loc = nn.Conv2D(512, 4, kernel_size=3, strides=1, padding='SAME')
|
||||
|
||||
|
||||
self.conv5_3_norm_mbox_conf = nn.Conv2D(512, 2, kernel_size=3, strides=1, padding='SAME')
|
||||
self.conv5_3_norm_mbox_loc = nn.Conv2D(512, 4, kernel_size=3, strides=1, padding='SAME')
|
||||
|
||||
|
||||
self.fc7_mbox_conf = nn.Conv2D(1024, 2, kernel_size=3, strides=1, padding='SAME')
|
||||
self.fc7_mbox_loc = nn.Conv2D(1024, 4, kernel_size=3, strides=1, padding='SAME')
|
||||
|
||||
|
||||
self.conv6_2_mbox_conf = nn.Conv2D(512, 2, kernel_size=3, strides=1, padding='SAME')
|
||||
self.conv6_2_mbox_loc = nn.Conv2D(512, 4, kernel_size=3, strides=1, padding='SAME')
|
||||
|
||||
|
||||
self.conv7_2_mbox_conf = nn.Conv2D(256, 2, kernel_size=3, strides=1, padding='SAME')
|
||||
self.conv7_2_mbox_loc = nn.Conv2D(256, 4, kernel_size=3, strides=1, padding='SAME')
|
||||
|
||||
|
||||
def forward(self, inp):
|
||||
x, = inp
|
||||
x = x - self.minus
|
||||
x = tf.nn.relu(self.conv1_1(x))
|
||||
x = tf.nn.relu(self.conv1_2(x))
|
||||
x = tf.nn.relu(self.conv1_2(x))
|
||||
x = tf.nn.max_pool(x, [1,2,2,1], [1,2,2,1], "VALID")
|
||||
|
||||
x = tf.nn.relu(self.conv2_1(x))
|
||||
x = tf.nn.relu(self.conv2_2(x))
|
||||
x = tf.nn.relu(self.conv2_2(x))
|
||||
x = tf.nn.max_pool(x, [1,2,2,1], [1,2,2,1], "VALID")
|
||||
|
||||
|
||||
x = tf.nn.relu(self.conv3_1(x))
|
||||
x = tf.nn.relu(self.conv3_2(x))
|
||||
x = tf.nn.relu(self.conv3_3(x))
|
||||
f3_3 = x
|
||||
x = tf.nn.relu(self.conv3_2(x))
|
||||
x = tf.nn.relu(self.conv3_3(x))
|
||||
f3_3 = x
|
||||
x = tf.nn.max_pool(x, [1,2,2,1], [1,2,2,1], "VALID")
|
||||
|
||||
x = tf.nn.relu(self.conv4_1(x))
|
||||
x = tf.nn.relu(self.conv4_2(x))
|
||||
x = tf.nn.relu(self.conv4_3(x))
|
||||
f4_3 = x
|
||||
x = tf.nn.relu(self.conv4_2(x))
|
||||
x = tf.nn.relu(self.conv4_3(x))
|
||||
f4_3 = x
|
||||
x = tf.nn.max_pool(x, [1,2,2,1], [1,2,2,1], "VALID")
|
||||
|
||||
x = tf.nn.relu(self.conv5_1(x))
|
||||
x = tf.nn.relu(self.conv5_2(x))
|
||||
x = tf.nn.relu(self.conv5_3(x))
|
||||
f5_3 = x
|
||||
x = tf.nn.relu(self.conv5_2(x))
|
||||
x = tf.nn.relu(self.conv5_3(x))
|
||||
f5_3 = x
|
||||
x = tf.nn.max_pool(x, [1,2,2,1], [1,2,2,1], "VALID")
|
||||
|
||||
x = tf.nn.relu(self.fc6(x))
|
||||
x = tf.nn.relu(self.fc7(x))
|
||||
ffc7 = x
|
||||
|
||||
|
||||
x = tf.nn.relu(self.conv6_1(x))
|
||||
x = tf.nn.relu(self.conv6_2(x))
|
||||
f6_2 = x
|
||||
|
||||
|
||||
x = tf.nn.relu(self.conv7_1(x))
|
||||
x = tf.nn.relu(self.conv7_2(x))
|
||||
f7_2 = x
|
||||
|
||||
|
||||
f3_3 = self.conv3_3_norm(f3_3)
|
||||
f4_3 = self.conv4_3_norm(f4_3)
|
||||
f5_3 = self.conv5_3_norm(f5_3)
|
||||
|
||||
|
||||
cls1 = self.conv3_3_norm_mbox_conf(f3_3)
|
||||
reg1 = self.conv3_3_norm_mbox_loc(f3_3)
|
||||
|
||||
|
||||
cls2 = tf.nn.softmax(self.conv4_3_norm_mbox_conf(f4_3))
|
||||
reg2 = self.conv4_3_norm_mbox_loc(f4_3)
|
||||
|
||||
|
||||
cls3 = tf.nn.softmax(self.conv5_3_norm_mbox_conf(f5_3))
|
||||
reg3 = self.conv5_3_norm_mbox_loc(f5_3)
|
||||
|
||||
|
||||
cls4 = tf.nn.softmax(self.fc7_mbox_conf(ffc7))
|
||||
reg4 = self.fc7_mbox_loc(ffc7)
|
||||
|
||||
|
||||
cls5 = tf.nn.softmax(self.conv6_2_mbox_conf(f6_2))
|
||||
reg5 = self.conv6_2_mbox_loc(f6_2)
|
||||
|
||||
|
||||
cls6 = tf.nn.softmax(self.conv7_2_mbox_conf(f7_2))
|
||||
reg6 = self.conv7_2_mbox_loc(f7_2)
|
||||
|
||||
# max-out background label
|
||||
bmax = tf.maximum(tf.maximum(cls1[:,:,:,0:1], cls1[:,:,:,1:2]), cls1[:,:,:,2:3])
|
||||
|
||||
bmax = tf.maximum(tf.maximum(cls1[:,:,:,0:1], cls1[:,:,:,1:2]), cls1[:,:,:,2:3])
|
||||
|
||||
cls1 = tf.concat ([bmax, cls1[:,:,:,3:4] ], axis=-1)
|
||||
cls1 = tf.nn.softmax(cls1)
|
||||
|
||||
|
||||
return [cls1, reg1, cls2, reg2, cls3, reg3, cls4, reg4, cls5, reg5, cls6, reg6]
|
||||
|
||||
e = None
|
||||
|
@ -165,10 +165,10 @@ class S3FDExtractor(object):
|
|||
if e is not None: e.__enter__()
|
||||
self.model = S3FD()
|
||||
self.model.load_weights (model_path)
|
||||
if e is not None: e.__exit__(None,None,None)
|
||||
|
||||
self.model.build_for_run ([ ( tf.float32, (None,None,3) ) ])
|
||||
|
||||
if e is not None: e.__exit__(None,None,None)
|
||||
|
||||
self.model.build_for_run ([ ( tf.float32, nn.get4Dshape (None,None,3) ) ])
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
|
@ -205,7 +205,7 @@ class S3FDExtractor(object):
|
|||
detected_faces = [ [(l,t,r,b), (r-l)*(b-t) ] for (l,t,r,b) in detected_faces ]
|
||||
detected_faces = sorted(detected_faces, key=operator.itemgetter(1), reverse=True )
|
||||
detected_faces = [ x[0] for x in detected_faces]
|
||||
|
||||
|
||||
if is_remove_intersects:
|
||||
for i in range( len(detected_faces)-1, 0, -1):
|
||||
l1,t1,r1,b1 = detected_faces[i]
|
||||
|
@ -214,8 +214,8 @@ class S3FDExtractor(object):
|
|||
dx = min(r0, r1) - max(l0, l1)
|
||||
dy = min(b0, b1) - max(t0, t1)
|
||||
if (dx>=0) and (dy>=0):
|
||||
detected_faces.pop(i)
|
||||
|
||||
detected_faces.pop(i)
|
||||
|
||||
return detected_faces
|
||||
|
||||
def refine(self, olist):
|
||||
|
|
|
@ -20,117 +20,117 @@ TernausNet: U-Net with VGG11 Encoder Pre-Trained on ImageNet for Image Segmentat
|
|||
class TernausNet(object):
|
||||
VERSION = 1
|
||||
def __init__ (self, name, resolution, face_type_str, load_weights=True, weights_file_root=None, training=False, place_model_on_cpu=False):
|
||||
nn.initialize()
|
||||
nn.initialize(data_format="NHWC")
|
||||
tf = nn.tf
|
||||
|
||||
|
||||
class Ternaus(nn.ModelBase):
|
||||
def on_build(self, in_ch, ch):
|
||||
|
||||
|
||||
self.features_0 = nn.Conv2D (in_ch, ch, kernel_size=3, padding='SAME')
|
||||
self.blurpool_0 = nn.BlurPool (filt_size=3)
|
||||
|
||||
|
||||
self.features_3 = nn.Conv2D (ch, ch*2, kernel_size=3, padding='SAME')
|
||||
self.blurpool_3 = nn.BlurPool (filt_size=3)
|
||||
|
||||
|
||||
self.features_6 = nn.Conv2D (ch*2, ch*4, kernel_size=3, padding='SAME')
|
||||
self.features_8 = nn.Conv2D (ch*4, ch*4, kernel_size=3, padding='SAME')
|
||||
self.blurpool_8 = nn.BlurPool (filt_size=3)
|
||||
|
||||
|
||||
self.features_11 = nn.Conv2D (ch*4, ch*8, kernel_size=3, padding='SAME')
|
||||
self.features_13 = nn.Conv2D (ch*8, ch*8, kernel_size=3, padding='SAME')
|
||||
self.blurpool_13 = nn.BlurPool (filt_size=3)
|
||||
|
||||
|
||||
self.features_16 = nn.Conv2D (ch*8, ch*8, kernel_size=3, padding='SAME')
|
||||
self.features_18 = nn.Conv2D (ch*8, ch*8, kernel_size=3, padding='SAME')
|
||||
self.blurpool_18 = nn.BlurPool (filt_size=3)
|
||||
|
||||
|
||||
self.conv_center = nn.Conv2D (ch*8, ch*8, kernel_size=3, padding='SAME')
|
||||
|
||||
|
||||
self.conv1_up = nn.Conv2DTranspose (ch*8, ch*4, kernel_size=3, padding='SAME')
|
||||
self.conv1 = nn.Conv2D (ch*12, ch*8, kernel_size=3, padding='SAME')
|
||||
|
||||
|
||||
self.conv2_up = nn.Conv2DTranspose (ch*8, ch*4, kernel_size=3, padding='SAME')
|
||||
self.conv2 = nn.Conv2D (ch*12, ch*8, kernel_size=3, padding='SAME')
|
||||
|
||||
|
||||
self.conv3_up = nn.Conv2DTranspose (ch*8, ch*2, kernel_size=3, padding='SAME')
|
||||
self.conv3 = nn.Conv2D (ch*6, ch*4, kernel_size=3, padding='SAME')
|
||||
|
||||
|
||||
self.conv4_up = nn.Conv2DTranspose (ch*4, ch, kernel_size=3, padding='SAME')
|
||||
self.conv4 = nn.Conv2D (ch*3, ch*2, kernel_size=3, padding='SAME')
|
||||
|
||||
|
||||
self.conv5_up = nn.Conv2DTranspose (ch*2, ch//2, kernel_size=3, padding='SAME')
|
||||
self.conv5 = nn.Conv2D (ch//2+ch, ch, kernel_size=3, padding='SAME')
|
||||
|
||||
|
||||
self.out_conv = nn.Conv2D (ch, 1, kernel_size=3, padding='SAME')
|
||||
|
||||
|
||||
def forward(self, inp):
|
||||
x, = inp
|
||||
|
||||
|
||||
x = x0 = tf.nn.relu(self.features_0(x))
|
||||
x = self.blurpool_0(x)
|
||||
|
||||
|
||||
x = x1 = tf.nn.relu(self.features_3(x))
|
||||
x = self.blurpool_3(x)
|
||||
|
||||
x = self.blurpool_3(x)
|
||||
|
||||
x = tf.nn.relu(self.features_6(x))
|
||||
x = x2 = tf.nn.relu(self.features_8(x))
|
||||
x = self.blurpool_8(x)
|
||||
|
||||
x = self.blurpool_8(x)
|
||||
|
||||
x = tf.nn.relu(self.features_11(x))
|
||||
x = x3 = tf.nn.relu(self.features_13(x))
|
||||
x = self.blurpool_13(x)
|
||||
|
||||
|
||||
x = tf.nn.relu(self.features_16(x))
|
||||
x = x4 = tf.nn.relu(self.features_18(x))
|
||||
x = self.blurpool_18(x)
|
||||
|
||||
|
||||
x = self.conv_center(x)
|
||||
|
||||
x = tf.nn.relu(self.conv1_up(x))
|
||||
|
||||
x = tf.nn.relu(self.conv1_up(x))
|
||||
x = tf.concat( [x,x4], -1)
|
||||
x = tf.nn.relu(self.conv1(x))
|
||||
|
||||
x = tf.nn.relu(self.conv2_up(x))
|
||||
|
||||
x = tf.nn.relu(self.conv2_up(x))
|
||||
x = tf.concat( [x,x3], -1)
|
||||
x = tf.nn.relu(self.conv2(x))
|
||||
|
||||
x = tf.nn.relu(self.conv3_up(x))
|
||||
|
||||
x = tf.nn.relu(self.conv3_up(x))
|
||||
x = tf.concat( [x,x2], -1)
|
||||
x = tf.nn.relu(self.conv3(x))
|
||||
|
||||
x = tf.nn.relu(self.conv4_up(x))
|
||||
|
||||
x = tf.nn.relu(self.conv4_up(x))
|
||||
x = tf.concat( [x,x1], -1)
|
||||
x = tf.nn.relu(self.conv4(x))
|
||||
|
||||
x = tf.nn.relu(self.conv5_up(x))
|
||||
|
||||
x = tf.nn.relu(self.conv5_up(x))
|
||||
x = tf.concat( [x,x0], -1)
|
||||
x = tf.nn.relu(self.conv5(x))
|
||||
|
||||
|
||||
x = tf.nn.sigmoid(self.out_conv(x))
|
||||
return x
|
||||
return x
|
||||
|
||||
if weights_file_root is not None:
|
||||
weights_file_root = Path(weights_file_root)
|
||||
else:
|
||||
weights_file_root = Path(__file__).parent
|
||||
self.weights_path = weights_file_root / ('%s_%d_%s.npy' % (name, resolution, face_type_str) )
|
||||
|
||||
|
||||
e = tf.device('/CPU:0') if place_model_on_cpu else None
|
||||
|
||||
|
||||
if e is not None: e.__enter__()
|
||||
self.net = Ternaus(3, 64, name='Ternaus')
|
||||
if load_weights:
|
||||
self.net.load_weights (self.weights_path)
|
||||
self.net = Ternaus(3, 64, name='Ternaus')
|
||||
if load_weights:
|
||||
self.net.load_weights (self.weights_path)
|
||||
else:
|
||||
self.net.init_weights()
|
||||
if e is not None: e.__exit__(None,None,None)
|
||||
|
||||
self.net.build_for_run ( [(tf.float32, (resolution,resolution,3))] )
|
||||
|
||||
if e is not None: e.__exit__(None,None,None)
|
||||
|
||||
self.net.build_for_run ( [(tf.float32, nn.get4Dshape (resolution,resolution,3) )] )
|
||||
|
||||
if training:
|
||||
raise Exception("training not supported yet")
|
||||
|
||||
|
||||
|
||||
|
||||
"""
|
||||
if training:
|
||||
try:
|
||||
|
@ -149,9 +149,9 @@ class TernausNet(object):
|
|||
if 'CA.' in layer.name:
|
||||
conv_weights_list += [layer.weights[0]] #Conv2D kernel_weights
|
||||
CAInitializerMP ( conv_weights_list )
|
||||
"""
|
||||
"""
|
||||
|
||||
|
||||
|
||||
"""
|
||||
if training:
|
||||
inp_t = Input ( (resolution, resolution, 3) )
|
||||
|
@ -195,124 +195,3 @@ class TernausNet(object):
|
|||
result = result[0]
|
||||
|
||||
return result
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
"""
|
||||
self.weights_path = weights_file_root / ('%s_%d_%s.h5' % (name, resolution, face_type_str) )
|
||||
|
||||
|
||||
self.net.build()
|
||||
|
||||
|
||||
self.net.features_0.set_weights ( self.model.get_layer('features.0').get_weights() )
|
||||
self.net.features_3.set_weights ( self.model.get_layer('features.3').get_weights() )
|
||||
self.net.features_6.set_weights ( self.model.get_layer('features.6').get_weights() )
|
||||
self.net.features_8.set_weights ( self.model.get_layer('features.8').get_weights() )
|
||||
self.net.features_11.set_weights ( self.model.get_layer('features.11').get_weights() )
|
||||
self.net.features_13.set_weights ( self.model.get_layer('features.13').get_weights() )
|
||||
self.net.features_16.set_weights ( self.model.get_layer('features.16').get_weights() )
|
||||
self.net.features_18.set_weights ( self.model.get_layer('features.18').get_weights() )
|
||||
|
||||
self.net.conv_center.set_weights ( self.model.get_layer('CA.1').get_weights() )
|
||||
|
||||
self.net.conv1_up.set_weights ( self.model.get_layer('CA.2').get_weights() )
|
||||
self.net.conv1.set_weights ( self.model.get_layer('CA.3').get_weights() )
|
||||
|
||||
self.net.conv2_up.set_weights ( self.model.get_layer('CA.4').get_weights() )
|
||||
self.net.conv2.set_weights ( self.model.get_layer('CA.5').get_weights() )
|
||||
|
||||
self.net.conv3_up.set_weights ( self.model.get_layer('CA.6').get_weights() )
|
||||
self.net.conv3.set_weights ( self.model.get_layer('CA.7').get_weights() )
|
||||
|
||||
self.net.conv4_up.set_weights ( self.model.get_layer('CA.8').get_weights() )
|
||||
self.net.conv4.set_weights ( self.model.get_layer('CA.9').get_weights() )
|
||||
|
||||
self.net.conv5_up.set_weights ( self.model.get_layer('CA.10').get_weights() )
|
||||
self.net.conv5.set_weights ( self.model.get_layer('CA.11').get_weights() )
|
||||
|
||||
self.net.out_conv.set_weights ( self.model.get_layer('CA.12').get_weights() )
|
||||
|
||||
self.net.build_for_run ( [ (tf.float32, (resolution,resolution,3)) ])
|
||||
self.net.save_weights (self.weights_path2)
|
||||
|
||||
|
||||
def extract (self, input_image):
|
||||
input_shape_len = len(input_image.shape)
|
||||
if input_shape_len == 3:
|
||||
input_image = input_image[np.newaxis,...]
|
||||
|
||||
result = np.clip ( self.model.predict( [input_image] ), 0, 1.0 )
|
||||
result[result < 0.1] = 0 #get rid of noise
|
||||
|
||||
if input_shape_len == 3:
|
||||
result = result[0]
|
||||
|
||||
return result
|
||||
|
||||
|
||||
@staticmethod
|
||||
def BuildModel ( resolution, ngf=64):
|
||||
exec( nn.initialize(), locals(), globals() )
|
||||
inp = Input ( (resolution,resolution,3) )
|
||||
x = inp
|
||||
x = TernausNet.Flow(ngf=ngf)(x)
|
||||
model = Model(inp,x)
|
||||
return model
|
||||
|
||||
@staticmethod
|
||||
def Flow(ngf=64):
|
||||
exec( nn.initialize(), locals(), globals() )
|
||||
|
||||
def func(input):
|
||||
x = input
|
||||
|
||||
x0 = x = Conv2D(ngf, kernel_size=3, strides=1, padding='same', activation='relu', name='features.0')(x)
|
||||
x = BlurPool(filt_size=3)(x)
|
||||
|
||||
x1 = x = Conv2D(ngf*2, kernel_size=3, strides=1, padding='same', activation='relu', name='features.3')(x)
|
||||
x = BlurPool(filt_size=3)(x)
|
||||
|
||||
x = Conv2D(ngf*4, kernel_size=3, strides=1, padding='same', activation='relu', name='features.6')(x)
|
||||
x2 = x = Conv2D(ngf*4, kernel_size=3, strides=1, padding='same', activation='relu', name='features.8')(x)
|
||||
x = BlurPool(filt_size=3)(x)
|
||||
|
||||
x = Conv2D(ngf*8, kernel_size=3, strides=1, padding='same', activation='relu', name='features.11')(x)
|
||||
x3 = x = Conv2D(ngf*8, kernel_size=3, strides=1, padding='same', activation='relu', name='features.13')(x)
|
||||
x = BlurPool(filt_size=3)(x)
|
||||
|
||||
x = Conv2D(ngf*8, kernel_size=3, strides=1, padding='same', activation='relu', name='features.16')(x)
|
||||
x4 = x = Conv2D(ngf*8, kernel_size=3, strides=1, padding='same', activation='relu', name='features.18')(x)
|
||||
x = BlurPool(filt_size=3)(x)
|
||||
|
||||
x = Conv2D(ngf*8, kernel_size=3, strides=1, padding='same', name='CA.1')(x)
|
||||
|
||||
x = Conv2DTranspose (ngf*4, 3, strides=2, padding='same', activation='relu', name='CA.2') (x)
|
||||
x = Concatenate(axis=3)([ x, x4])
|
||||
x = Conv2D (ngf*8, 3, strides=1, padding='same', activation='relu', name='CA.3') (x)
|
||||
|
||||
x = Conv2DTranspose (ngf*4, 3, strides=2, padding='same', activation='relu', name='CA.4') (x)
|
||||
x = Concatenate(axis=3)([ x, x3])
|
||||
x = Conv2D (ngf*8, 3, strides=1, padding='same', activation='relu', name='CA.5') (x)
|
||||
|
||||
x = Conv2DTranspose (ngf*2, 3, strides=2, padding='same', activation='relu', name='CA.6') (x)
|
||||
x = Concatenate(axis=3)([ x, x2])
|
||||
x = Conv2D (ngf*4, 3, strides=1, padding='same', activation='relu', name='CA.7') (x)
|
||||
|
||||
x = Conv2DTranspose (ngf, 3, strides=2, padding='same', activation='relu', name='CA.8') (x)
|
||||
x = Concatenate(axis=3)([ x, x1])
|
||||
x = Conv2D (ngf*2, 3, strides=1, padding='same', activation='relu', name='CA.9') (x)
|
||||
|
||||
x = Conv2DTranspose (ngf // 2, 3, strides=2, padding='same', activation='relu', name='CA.10') (x)
|
||||
x = Concatenate(axis=3)([ x, x0])
|
||||
x = Conv2D (ngf, 3, strides=1, padding='same', activation='relu', name='CA.11') (x)
|
||||
|
||||
return Conv2D(1, 3, strides=1, padding='same', activation='sigmoid', name='CA.12')(x)
|
||||
|
||||
|
||||
return func
|
||||
"""
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue