DFL-2.0 initial branch commit

This commit is contained in:
Colombo 2020-01-21 18:43:39 +04:00
parent 52a67a61b3
commit 38b85108b3
154 changed files with 5251 additions and 9414 deletions

View file

@ -4,21 +4,171 @@ from pathlib import Path
import cv2
import numpy as np
from nnlib import nnlib
from core.leras import nn
class S3FDExtractor(object):
def __init__(self, do_dummy_predict=False):
exec( nnlib.import_all(), locals(), globals() )
model_path = Path(__file__).parent / "S3FD.h5"
if not model_path.exists():
return None
self.model = nnlib.keras.models.load_model ( str(model_path) )
def __init__(self, place_model_on_cpu=False):
nn.initialize()
tf = nn.tf
if do_dummy_predict:
self.extract ( np.zeros( (640,640,3), dtype=np.uint8) )
model_path = Path(__file__).parent / "S3FD.npy"
if not model_path.exists():
raise Exception("Unable to load S3FD.npy")
class L2Norm(nn.LayerBase):
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.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.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.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.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.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])
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
if place_model_on_cpu:
e = tf.device("/CPU:0")
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) ) ])
def __enter__(self):
return self
@ -40,7 +190,7 @@ class S3FDExtractor(object):
input_scale = d / scale_to
input_image = cv2.resize (input_image, ( int(w/input_scale), int(h/input_scale) ), interpolation=cv2.INTER_LINEAR)
olist = self.model.predict( np.expand_dims(input_image,0) )
olist = self.model.run ([ input_image[None,...] ] )
detected_faces = []
for ltrb in self.refine (olist):
@ -75,8 +225,8 @@ class S3FDExtractor(object):
s_d2 = stride / 2
s_m4 = stride * 4
for hindex, windex in zip(*np.where(ocls > 0.05)):
score = ocls[hindex, windex]
for hindex, windex in zip(*np.where(ocls[...,1] > 0.05)):
score = ocls[hindex, windex, 1]
loc = oreg[hindex, windex, :]
priors = np.array([windex * stride + s_d2, hindex * stride + s_d2, s_m4, s_m4])
priors_2p = priors[2:]