first commit
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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("----------------------------------------------------------------")
|
||||
@@ -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
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user