first commit

This commit is contained in:
Your Name
2019-02-01 15:30:41 +08:00
commit df2c0c06fa
81 changed files with 1765 additions and 0 deletions
+101
View File
@@ -0,0 +1,101 @@
"""
This file using for extracting faces of all images
"""
import glob
try:
import dlib
except ImportError:
print('You have not installed dlib, install from https://github.com/davisking/dlib')
print('see you later.')
exit(0)
import os
import cv2
import numpy as np
from loguru import logger
class FaceExtractor(object):
def __init__(self):
self.detector = dlib.get_frontal_face_detector()
# self.predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
self.predictor_path = os.path.expanduser('~/shape_predictor_68_face_landmarks.dat')
def get_faces_list(self, img, landmark=False):
"""
get faces and locations
"""
assert isinstance(img, np.ndarray), 'img should be numpy array (cv2 frame)'
if landmark:
if os.path.exists(self.predictor_path):
predictor = dlib.shape_predictor(self.predictor_path)
else:
logger.error('can not call this method, you should download '
'dlib landmark model: http://dlib.net/files/shape_predictor_68_face_landmarks.dat.bz2')
exit(0)
dets = self.detector(img, 1)
all_faces = []
locations = []
landmarks = []
for i, d in enumerate(dets):
# get the face crop
x = int(d.left())
y = int(d.top())
w = int(d.width())
h = int(d.height())
face_patch = np.array(img)[y: y + h, x: x + w, 0:3]
if landmark:
shape = predictor(img, d)
landmarks.append(shape)
locations.append([x, y, w, h])
all_faces.append(face_patch)
if landmark:
return all_faces, locations, landmarks
else:
return all_faces, locations
def get_faces(self, img_d):
"""
get all faces from img_d
:param img_d:
:return:
"""
all_images = []
for e in ['png', 'jpg', 'jpeg']:
all_images.extend(glob.glob(os.path.join(img_d, '*.{}'.format(e))))
print('Found all {} images under {}'.format(len(all_images), img_d))
s_d = os.path.dirname(img_d) + "_faces"
if not os.path.exists(s_d):
os.makedirs(s_d)
for img_f in all_images:
img = cv2.imread(img_f, cv2.COLOR_BGR2RGB)
dets = self.detector(img, 1)
print('=> get {} faces in {}'.format(len(dets), img_f))
print('=> saving faces...')
for i, d in enumerate(dets):
save_face_f = os.path.join(s_d, os.path.basename(img_f).split('.')[0]
+ '_face_{}.png'.format(i))
# get the face crop
x = int(d.left())
y = int(d.top())
w = int(d.width())
h = int(d.height())
face_patch = np.array(img)[y: y + h, x: x + w, 0:3]
# print(face_patch.shape)
img = cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 255), 2)
# cv2.imshow('tt', img)
# cv2.waitKey(0)
cv2.imwrite(save_face_f, face_patch)
print('Done!')
# cv2.waitKey(0)
+129
View File
@@ -0,0 +1,129 @@
# -----------------------
#
# Copyright Jin Fagang @2018
#
# 1/25/19
# torch_summary
# -----------------------
"""
codes token from
https://github.com/sksq96/pytorch-summary
I edit something here, credits belongs to author
"""
import torch
import torch.nn as nn
from torch.autograd import Variable
from collections import OrderedDict
import numpy as np
def summary(model, input_size, batch_size=-1, device="cuda"):
def register_hook(module):
def hook(module, input, output):
class_name = str(module.__class__).split(".")[-1].split("'")[0]
module_idx = len(summary)
m_key = "%s-%i" % (class_name, module_idx + 1)
summary[m_key] = OrderedDict()
summary[m_key]["input_shape"] = list(input[0].size())
summary[m_key]["input_shape"][0] = batch_size
if isinstance(output, (list, tuple)):
summary[m_key]["output_shape"] = [
[-1] + list(o.size())[1:] for o in output
]
else:
summary[m_key]["output_shape"] = list(output.size())
summary[m_key]["output_shape"][0] = batch_size
params = 0
if hasattr(module, "weight") and hasattr(module.weight, "size"):
params += torch.prod(torch.LongTensor(list(module.weight.size())))
summary[m_key]["trainable"] = module.weight.requires_grad
if hasattr(module, "bias") and hasattr(module.bias, "size"):
params += torch.prod(torch.LongTensor(list(module.bias.size())))
summary[m_key]["nb_params"] = params
if (
not isinstance(module, nn.Sequential)
and not isinstance(module, nn.ModuleList)
and not (module == model)
):
hooks.append(module.register_forward_hook(hook))
device = device.lower()
assert device in [
"cuda",
"cpu",
], "Input device is not valid, please specify 'cuda' or 'cpu'"
if device == "cuda" and torch.cuda.is_available():
dtype = torch.cuda.FloatTensor
else:
dtype = torch.FloatTensor
# multiple inputs to the network
if isinstance(input_size, tuple) and input_size[0] <= 3:
# batch_size of 2 for batchnorm
x = torch.rand(2, *input_size).type(dtype)
else:
print('Wrong! you should send input size specific without batch size, etc: (3, 64, 64), channel first.')
exit(0)
# create properties
summary = OrderedDict()
hooks = []
# register hook
model.apply(register_hook)
# make a forward pass
try:
print('fake data input: ', x.size())
model(x)
except Exception as e:
print('summary failed. error: {}'.format(e))
print('make sure your called model.to(device) ')
exit(0)
# remove these hooks
for h in hooks:
h.remove()
print("----------------------------------------------------------------")
line_new = "{:>20} {:>25} {:>15}".format("Layer (type)", "Output Shape", "Param #")
print(line_new)
print("================================================================")
total_params = 0
total_output = 0
trainable_params = 0
for layer in summary:
# input_shape, output_shape, trainable, nb_params
line_new = "{:>20} {:>25} {:>15}".format(
layer,
str(summary[layer]["output_shape"]),
"{0:,}".format(summary[layer]["nb_params"]),
)
total_params += summary[layer]["nb_params"]
total_output += np.prod(summary[layer]["output_shape"])
if "trainable" in summary[layer]:
if summary[layer]["trainable"] == True:
trainable_params += summary[layer]["nb_params"]
print(line_new)
# assume 4 bytes/number (float on cuda).
total_input_size = abs(np.prod(input_size) * batch_size * 4. / (1024 ** 2.))
total_output_size = abs(2. * total_output * 4. / (1024 ** 2.)) # x2 for gradients
total_params_size = abs(total_params.numpy() * 4. / (1024 ** 2.))
total_size = total_params_size + total_output_size + total_input_size
print("================================================================")
print("Total params: {0:,}".format(total_params))
print("Trainable params: {0:,}".format(trainable_params))
print("Non-trainable params: {0:,}".format(total_params - trainable_params))
print("----------------------------------------------------------------")
print("Input size (MB): %0.2f" % total_input_size)
print("Forward/backward pass size (MB): %0.2f" % total_output_size)
print("Params size (MB): %0.2f" % total_params_size)
print("Estimated Total Size (MB): %0.2f" % total_size)
print("----------------------------------------------------------------")
+88
View File
@@ -0,0 +1,88 @@
# # License (Modified BSD) # Copyright (C) 2011, the scikit-image team All rights reserved. # # Redistribution and
# use in source and binary forms, with or without modification, are permitted provided that the following conditions
# are met: # # Redistributions of source code must retain the above copyright notice, this list of conditions and the
# following disclaimer. # Redistributions in binary form must reproduce the above copyright notice, this list of
# conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
# Neither the name of skimage nor the names of its contributors may be used to endorse or promote products derived
# from this software without specific prior written permission. # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS''
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
# FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# umeyama function from scikit-image/skimage/transform/_geometric.py
import numpy as np
def umeyama(src, dst, estimate_scale):
"""Estimate N-D similarity transformation with or without scaling.
Parameters
----------
src : (M, N) array
Source coordinates.
dst : (M, N) array
Destination coordinates.
estimate_scale : bool
Whether to estimate scaling factor.
Returns
-------
T : (N + 1, N + 1)
The homogeneous similarity transformation matrix. The matrix contains
NaN values only if the problem is not well-conditioned.
References
----------
.. [1] "Least-squares estimation of transformation parameters between two
point patterns", Shinji Umeyama, PAMI 1991, DOI: 10.1109/34.88573
"""
num = src.shape[0]
dim = src.shape[1]
# Compute mean of src and dst.
src_mean = src.mean(axis=0)
dst_mean = dst.mean(axis=0)
# Subtract mean from src and dst.
src_demean = src - src_mean
dst_demean = dst - dst_mean
# Eq. (38).
A = np.dot(dst_demean.T, src_demean) / num
# Eq. (39).
d = np.ones((dim,), dtype=np.double)
if np.linalg.det(A) < 0:
d[dim - 1] = -1
T = np.eye(dim + 1, dtype=np.double)
U, S, V = np.linalg.svd(A)
# Eq. (40) and (43).
rank = np.linalg.matrix_rank(A)
if rank == 0:
return np.nan * T
elif rank == dim - 1:
if np.linalg.det(U) * np.linalg.det(V) > 0:
T[:dim, :dim] = np.dot(U, V)
else:
s = d[dim - 1]
d[dim - 1] = -1
T[:dim, :dim] = np.dot(U, np.dot(np.diag(d), V))
d[dim - 1] = s
else:
T[:dim, :dim] = np.dot(U, np.dot(np.diag(d), V.T))
if estimate_scale:
# Eq. (41) and (42).
scale = 1.0 / src_demean.var(axis=0).sum() * np.dot(S, d)
else:
scale = 1.0
T[:dim, dim] = dst_mean - scale * np.dot(T[:dim, :dim], src_mean.T)
T[:dim, :dim] *= scale
return T
+40
View File
@@ -0,0 +1,40 @@
import cv2
import numpy
import os
def get_image_paths(directory):
# return [x.path for x in os.scandir(directory) if x.name.endswith(".jpg") or x.name.endswith(".png")]
return [x.path for x in os.scandir(directory) if x.name.endswith(".png")]
def load_images(image_paths, convert=None):
iter_all_images = (cv2.resize(cv2.imread(fn), (256, 256)) for fn in image_paths)
if convert:
iter_all_images = (convert(img) for img in iter_all_images)
for i, image in enumerate(iter_all_images):
if i == 0:
all_images = numpy.empty((len(image_paths),) + image.shape, dtype=image.dtype)
all_images[i] = image
return all_images
def get_transpose_axes(n):
if n % 2 == 0:
y_axes = list(range(1, n - 1, 2))
x_axes = list(range(0, n - 1, 2))
else:
y_axes = list(range(0, n - 1, 2))
x_axes = list(range(1, n - 1, 2))
return y_axes, x_axes, [n - 1]
def stack_images(images):
images_shape = numpy.array(images.shape)
new_axes = get_transpose_axes(len(images_shape))
new_shape = [numpy.prod(images_shape[x]) for x in new_axes]
return numpy.transpose(
images,
axes=numpy.concatenate(new_axes)
).reshape(new_shape)