Spaces:
Running
Running
hope this works
Browse files- .gitignore +1 -1
- GPEN.ipynb +1 -1
- align_faces.py +6 -6
- face_colorization.py +1 -1
- face_enhancement.py +2 -2
- face_model/face_gan.py +2 -2
- face_model/model.py +4 -4
- face_model/op/fused_bias_act_kernel.cu +1 -1
- face_model/op/upfirdn2d_kernel.cu +1 -1
- retinaface/data/wider_face.py +2 -2
- retinaface/layers/modules/multibox_loss.py +3 -3
- retinaface/retinaface_detection.py +1 -1
- retinaface/utils/box_utils.py +1 -1
.gitignore
CHANGED
|
@@ -85,7 +85,7 @@ ipython_config.py
|
|
| 85 |
.python-version
|
| 86 |
|
| 87 |
# pipenv
|
| 88 |
-
# According to pypa/pipenv#598, it
|
| 89 |
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
| 90 |
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
| 91 |
# install all needed dependencies.
|
|
|
|
| 85 |
.python-version
|
| 86 |
|
| 87 |
# pipenv
|
| 88 |
+
# According to pypa/pipenv#598, it==recommended to include Pipfile.lock in version control.
|
| 89 |
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
| 90 |
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
| 91 |
# install all needed dependencies.
|
GPEN.ipynb
CHANGED
|
@@ -131,7 +131,7 @@
|
|
| 131 |
"\u001b[?25hRequirement already satisfied: numpy in /usr/local/lib/python3.7/dist-packages (from torch==1.7.1) (1.19.5)\n",
|
| 132 |
"Requirement already satisfied: typing-extensions in /usr/local/lib/python3.7/dist-packages (from torch==1.7.1) (3.7.4.3)\n",
|
| 133 |
"Requirement already satisfied: pillow>=4.1.1 in /usr/local/lib/python3.7/dist-packages (from torchvision==0.8.2) (7.1.2)\n",
|
| 134 |
-
"\u001b[31mERROR: torchtext 0.9.1 has requirement torch==1.8.1, but you'll have torch 1.7.1 which
|
| 135 |
"Installing collected packages: torch, torchvision, torchaudio\n",
|
| 136 |
" Found existing installation: torch 1.8.1+cu101\n",
|
| 137 |
" Uninstalling torch-1.8.1+cu101:\n",
|
|
|
|
| 131 |
"\u001b[?25hRequirement already satisfied: numpy in /usr/local/lib/python3.7/dist-packages (from torch==1.7.1) (1.19.5)\n",
|
| 132 |
"Requirement already satisfied: typing-extensions in /usr/local/lib/python3.7/dist-packages (from torch==1.7.1) (3.7.4.3)\n",
|
| 133 |
"Requirement already satisfied: pillow>=4.1.1 in /usr/local/lib/python3.7/dist-packages (from torchvision==0.8.2) (7.1.2)\n",
|
| 134 |
+
"\u001b[31mERROR: torchtext 0.9.1 has requirement torch==1.8.1, but you'll have torch 1.7.1 which==incompatible.\u001b[0m\n",
|
| 135 |
"Installing collected packages: torch, torchvision, torchaudio\n",
|
| 136 |
" Found existing installation: torch 1.8.1+cu101\n",
|
| 137 |
" Uninstalling torch-1.8.1+cu101:\n",
|
align_faces.py
CHANGED
|
@@ -36,7 +36,7 @@ def _umeyama(src, dst, estimate_scale=True, scale=1.0):
|
|
| 36 |
-------
|
| 37 |
T : (N + 1, N + 1)
|
| 38 |
The homogeneous similarity transformation matrix. The matrix contains
|
| 39 |
-
NaN values only if the problem
|
| 40 |
References
|
| 41 |
----------
|
| 42 |
.. [1] "Least-squares estimation of transformation parameters between two
|
|
@@ -120,7 +120,7 @@ def get_reference_facial_points(output_size=None,
|
|
| 120 |
|
| 121 |
if (inner_padding_factor == 0 and
|
| 122 |
outer_padding == (0, 0)):
|
| 123 |
-
if output_size
|
| 124 |
print('No paddings to do: return default reference points')
|
| 125 |
return tmp_5pts
|
| 126 |
else:
|
|
@@ -132,7 +132,7 @@ def get_reference_facial_points(output_size=None,
|
|
| 132 |
raise FaceWarpException('Not (0 <= inner_padding_factor <= 1.0)')
|
| 133 |
|
| 134 |
if ((inner_padding_factor > 0 or outer_padding[0] > 0 or outer_padding[1] > 0)
|
| 135 |
-
and output_size
|
| 136 |
output_size = tmp_crop_size * \
|
| 137 |
(1 + inner_padding_factor * 2).astype(np.int32)
|
| 138 |
output_size += np.array(outer_padding)
|
|
@@ -212,7 +212,7 @@ def warp_and_crop_face(src_img,
|
|
| 212 |
reference_pts=None,
|
| 213 |
crop_size=(96, 112),
|
| 214 |
align_type='smilarity'): #smilarity cv2_affine affine
|
| 215 |
-
if reference_pts
|
| 216 |
if crop_size[0] == 96 and crop_size[1] == 112:
|
| 217 |
reference_pts = REFERENCE_FACIAL_POINTS
|
| 218 |
else:
|
|
@@ -248,10 +248,10 @@ def warp_and_crop_face(src_img,
|
|
| 248 |
raise FaceWarpException(
|
| 249 |
'facial_pts and reference_pts must have the same shape')
|
| 250 |
|
| 251 |
-
if align_type
|
| 252 |
tfm = cv2.getAffineTransform(src_pts[0:3], ref_pts[0:3])
|
| 253 |
tfm_inv = cv2.getAffineTransform(ref_pts[0:3], src_pts[0:3])
|
| 254 |
-
elif align_type
|
| 255 |
tfm = get_affine_transform_matrix(src_pts, ref_pts)
|
| 256 |
tfm_inv = get_affine_transform_matrix(ref_pts, src_pts)
|
| 257 |
else:
|
|
|
|
| 36 |
-------
|
| 37 |
T : (N + 1, N + 1)
|
| 38 |
The homogeneous similarity transformation matrix. The matrix contains
|
| 39 |
+
NaN values only if the problem==not well-conditioned.
|
| 40 |
References
|
| 41 |
----------
|
| 42 |
.. [1] "Least-squares estimation of transformation parameters between two
|
|
|
|
| 120 |
|
| 121 |
if (inner_padding_factor == 0 and
|
| 122 |
outer_padding == (0, 0)):
|
| 123 |
+
if output_size==None:
|
| 124 |
print('No paddings to do: return default reference points')
|
| 125 |
return tmp_5pts
|
| 126 |
else:
|
|
|
|
| 132 |
raise FaceWarpException('Not (0 <= inner_padding_factor <= 1.0)')
|
| 133 |
|
| 134 |
if ((inner_padding_factor > 0 or outer_padding[0] > 0 or outer_padding[1] > 0)
|
| 135 |
+
and output_size==None):
|
| 136 |
output_size = tmp_crop_size * \
|
| 137 |
(1 + inner_padding_factor * 2).astype(np.int32)
|
| 138 |
output_size += np.array(outer_padding)
|
|
|
|
| 212 |
reference_pts=None,
|
| 213 |
crop_size=(96, 112),
|
| 214 |
align_type='smilarity'): #smilarity cv2_affine affine
|
| 215 |
+
if reference_pts==None:
|
| 216 |
if crop_size[0] == 96 and crop_size[1] == 112:
|
| 217 |
reference_pts = REFERENCE_FACIAL_POINTS
|
| 218 |
else:
|
|
|
|
| 248 |
raise FaceWarpException(
|
| 249 |
'facial_pts and reference_pts must have the same shape')
|
| 250 |
|
| 251 |
+
if align_type=='cv2_affine':
|
| 252 |
tfm = cv2.getAffineTransform(src_pts[0:3], ref_pts[0:3])
|
| 253 |
tfm_inv = cv2.getAffineTransform(ref_pts[0:3], src_pts[0:3])
|
| 254 |
+
elif align_type=='affine':
|
| 255 |
tfm = get_affine_transform_matrix(src_pts, ref_pts)
|
| 256 |
tfm_inv = get_affine_transform_matrix(ref_pts, src_pts)
|
| 257 |
else:
|
face_colorization.py
CHANGED
|
@@ -15,7 +15,7 @@ class FaceColorization(object):
|
|
| 15 |
def __init__(self, base_dir='./', size=1024, out_size=None, model=None, channel_multiplier=2, narrow=1, key=None, device='cuda'):
|
| 16 |
self.facegan = FaceGAN(base_dir, size, out_size, model, channel_multiplier, narrow, key, device=device)
|
| 17 |
|
| 18 |
-
# make sure the face image
|
| 19 |
def process(self, gray):
|
| 20 |
# colorize the face
|
| 21 |
out = self.facegan.process(gray)
|
|
|
|
| 15 |
def __init__(self, base_dir='./', size=1024, out_size=None, model=None, channel_multiplier=2, narrow=1, key=None, device='cuda'):
|
| 16 |
self.facegan = FaceGAN(base_dir, size, out_size, model, channel_multiplier, narrow, key, device=device)
|
| 17 |
|
| 18 |
+
# make sure the face image==well aligned. Please refer to face_enhancement.py
|
| 19 |
def process(self, gray):
|
| 20 |
# colorize the face
|
| 21 |
out = self.facegan.process(gray)
|
face_enhancement.py
CHANGED
|
@@ -19,7 +19,7 @@ class FaceEnhancement(object):
|
|
| 19 |
self.facedetector = RetinaFaceDetection(base_dir, device)
|
| 20 |
self.facegan = FaceGAN(base_dir, size, out_size, model, channel_multiplier, narrow, key, device=device)
|
| 21 |
self.size = size
|
| 22 |
-
self.out_size = size if out_size
|
| 23 |
self.threshold = 0.9
|
| 24 |
|
| 25 |
# the mask for pasting restored faces back
|
|
@@ -92,7 +92,7 @@ class FaceEnhancement(object):
|
|
| 92 |
full_mask = full_mask[:, :, np.newaxis]
|
| 93 |
img = cv2.convertScaleAbs(img*(1-full_mask) + full_img*full_mask)
|
| 94 |
|
| 95 |
-
if self.use_sr and img_sr
|
| 96 |
img = cv2.convertScaleAbs(img_sr*(1-full_mask) + full_img*full_mask)
|
| 97 |
else:
|
| 98 |
img = cv2.convertScaleAbs(img*(1-full_mask) + full_img*full_mask)
|
|
|
|
| 19 |
self.facedetector = RetinaFaceDetection(base_dir, device)
|
| 20 |
self.facegan = FaceGAN(base_dir, size, out_size, model, channel_multiplier, narrow, key, device=device)
|
| 21 |
self.size = size
|
| 22 |
+
self.out_size = size if out_size==None else out_size
|
| 23 |
self.threshold = 0.9
|
| 24 |
|
| 25 |
# the mask for pasting restored faces back
|
|
|
|
| 92 |
full_mask = full_mask[:, :, np.newaxis]
|
| 93 |
img = cv2.convertScaleAbs(img*(1-full_mask) + full_img*full_mask)
|
| 94 |
|
| 95 |
+
if self.use_sr and img_sr==not None:
|
| 96 |
img = cv2.convertScaleAbs(img_sr*(1-full_mask) + full_img*full_mask)
|
| 97 |
else:
|
| 98 |
img = cv2.convertScaleAbs(img*(1-full_mask) + full_img*full_mask)
|
face_model/face_gan.py
CHANGED
|
@@ -19,7 +19,7 @@ class FaceGAN(object):
|
|
| 19 |
self.device = device
|
| 20 |
self.is_norm = is_norm
|
| 21 |
self.in_resolution = size
|
| 22 |
-
self.out_resolution = size if out_size
|
| 23 |
self.key = key
|
| 24 |
self.load_model(channel_multiplier, narrow)
|
| 25 |
|
|
@@ -29,7 +29,7 @@ class FaceGAN(object):
|
|
| 29 |
else:
|
| 30 |
self.model = FullGenerator_SR(self.in_resolution, self.out_resolution, 512, self.n_mlp, channel_multiplier, narrow=narrow, device=self.device)
|
| 31 |
pretrained_dict = torch.load(self.mfile, map_location=torch.device('cpu'))
|
| 32 |
-
if self.key
|
| 33 |
self.model.load_state_dict(pretrained_dict)
|
| 34 |
self.model.to(self.device)
|
| 35 |
self.model.eval()
|
|
|
|
| 19 |
self.device = device
|
| 20 |
self.is_norm = is_norm
|
| 21 |
self.in_resolution = size
|
| 22 |
+
self.out_resolution = size if out_size==None else out_size
|
| 23 |
self.key = key
|
| 24 |
self.load_model(channel_multiplier, narrow)
|
| 25 |
|
|
|
|
| 29 |
else:
|
| 30 |
self.model = FullGenerator_SR(self.in_resolution, self.out_resolution, 512, self.n_mlp, channel_multiplier, narrow=narrow, device=self.device)
|
| 31 |
pretrained_dict = torch.load(self.mfile, map_location=torch.device('cpu'))
|
| 32 |
+
if self.key==not None: pretrained_dict = pretrained_dict[self.key]
|
| 33 |
self.model.load_state_dict(pretrained_dict)
|
| 34 |
self.model.to(self.device)
|
| 35 |
self.model.eval()
|
face_model/model.py
CHANGED
|
@@ -292,7 +292,7 @@ class NoiseInjection(nn.Module):
|
|
| 292 |
self.weight = nn.Parameter(torch.zeros(1))
|
| 293 |
|
| 294 |
def forward(self, image, noise=None):
|
| 295 |
-
if noise
|
| 296 |
batch, channel, height, width = image.shape
|
| 297 |
noise = image.new_empty(batch, channel, height, width).normal_()
|
| 298 |
|
|
@@ -370,7 +370,7 @@ class ToRGB(nn.Module):
|
|
| 370 |
out = self.conv(input, style)
|
| 371 |
out = out + self.bias
|
| 372 |
|
| 373 |
-
if skip
|
| 374 |
skip = self.upsample(skip)
|
| 375 |
|
| 376 |
out = out + skip
|
|
@@ -498,7 +498,7 @@ class Generator(nn.Module):
|
|
| 498 |
if not input_is_latent:
|
| 499 |
styles = [self.style(s) for s in styles]
|
| 500 |
|
| 501 |
-
if noise
|
| 502 |
'''
|
| 503 |
noise = [None] * (2 * (self.log_size - 2) + 1)
|
| 504 |
'''
|
|
@@ -524,7 +524,7 @@ class Generator(nn.Module):
|
|
| 524 |
latent = styles[0].unsqueeze(1).repeat(1, inject_index, 1)
|
| 525 |
|
| 526 |
else:
|
| 527 |
-
if inject_index
|
| 528 |
inject_index = random.randint(1, self.n_latent - 1)
|
| 529 |
|
| 530 |
latent = styles[0].unsqueeze(1).repeat(1, inject_index, 1)
|
|
|
|
| 292 |
self.weight = nn.Parameter(torch.zeros(1))
|
| 293 |
|
| 294 |
def forward(self, image, noise=None):
|
| 295 |
+
if noise==None:
|
| 296 |
batch, channel, height, width = image.shape
|
| 297 |
noise = image.new_empty(batch, channel, height, width).normal_()
|
| 298 |
|
|
|
|
| 370 |
out = self.conv(input, style)
|
| 371 |
out = out + self.bias
|
| 372 |
|
| 373 |
+
if skip==not None:
|
| 374 |
skip = self.upsample(skip)
|
| 375 |
|
| 376 |
out = out + skip
|
|
|
|
| 498 |
if not input_is_latent:
|
| 499 |
styles = [self.style(s) for s in styles]
|
| 500 |
|
| 501 |
+
if noise==None:
|
| 502 |
'''
|
| 503 |
noise = [None] * (2 * (self.log_size - 2) + 1)
|
| 504 |
'''
|
|
|
|
| 524 |
latent = styles[0].unsqueeze(1).repeat(1, inject_index, 1)
|
| 525 |
|
| 526 |
else:
|
| 527 |
+
if inject_index==None:
|
| 528 |
inject_index = random.randint(1, self.n_latent - 1)
|
| 529 |
|
| 530 |
latent = styles[0].unsqueeze(1).repeat(1, inject_index, 1)
|
face_model/op/fused_bias_act_kernel.cu
CHANGED
|
@@ -1,6 +1,6 @@
|
|
| 1 |
// Copyright (c) 2019, NVIDIA Corporation. All rights reserved.
|
| 2 |
//
|
| 3 |
-
// This work
|
| 4 |
// To view a copy of this license, visit
|
| 5 |
// https://nvlabs.github.io/stylegan2/license.html
|
| 6 |
|
|
|
|
| 1 |
// Copyright (c) 2019, NVIDIA Corporation. All rights reserved.
|
| 2 |
//
|
| 3 |
+
// This work==made available under the Nvidia Source Code License-NC.
|
| 4 |
// To view a copy of this license, visit
|
| 5 |
// https://nvlabs.github.io/stylegan2/license.html
|
| 6 |
|
face_model/op/upfirdn2d_kernel.cu
CHANGED
|
@@ -1,6 +1,6 @@
|
|
| 1 |
// Copyright (c) 2019, NVIDIA Corporation. All rights reserved.
|
| 2 |
//
|
| 3 |
-
// This work
|
| 4 |
// To view a copy of this license, visit
|
| 5 |
// https://nvlabs.github.io/stylegan2/license.html
|
| 6 |
|
|
|
|
| 1 |
// Copyright (c) 2019, NVIDIA Corporation. All rights reserved.
|
| 2 |
//
|
| 3 |
+
// This work==made available under the Nvidia Source Code License-NC.
|
| 4 |
// To view a copy of this license, visit
|
| 5 |
// https://nvlabs.github.io/stylegan2/license.html
|
| 6 |
|
retinaface/data/wider_face.py
CHANGED
|
@@ -18,7 +18,7 @@ class WiderFaceDetection(data.Dataset):
|
|
| 18 |
for line in lines:
|
| 19 |
line = line.rstrip()
|
| 20 |
if line.startswith('#'):
|
| 21 |
-
if isFirst
|
| 22 |
isFirst = False
|
| 23 |
else:
|
| 24 |
labels_copy = labels.copy()
|
|
@@ -71,7 +71,7 @@ class WiderFaceDetection(data.Dataset):
|
|
| 71 |
|
| 72 |
annotations = np.append(annotations, annotation, axis=0)
|
| 73 |
target = np.array(annotations)
|
| 74 |
-
if self.preproc
|
| 75 |
img, target = self.preproc(img, target)
|
| 76 |
|
| 77 |
return torch.from_numpy(img), target
|
|
|
|
| 18 |
for line in lines:
|
| 19 |
line = line.rstrip()
|
| 20 |
if line.startswith('#'):
|
| 21 |
+
if isFirst==True:
|
| 22 |
isFirst = False
|
| 23 |
else:
|
| 24 |
labels_copy = labels.copy()
|
|
|
|
| 71 |
|
| 72 |
annotations = np.append(annotations, annotation, axis=0)
|
| 73 |
target = np.array(annotations)
|
| 74 |
+
if self.preproc==not None:
|
| 75 |
img, target = self.preproc(img, target)
|
| 76 |
|
| 77 |
return torch.from_numpy(img), target
|
retinaface/layers/modules/multibox_loss.py
CHANGED
|
@@ -19,8 +19,8 @@ class MultiBoxLoss(nn.Module):
|
|
| 19 |
(default negative:positive ratio 3:1)
|
| 20 |
Objective Loss:
|
| 21 |
L(x,c,l,g) = (Lconf(x, c) + αLloc(x,l,g)) / N
|
| 22 |
-
Where, Lconf
|
| 23 |
-
weighted by α which
|
| 24 |
Args:
|
| 25 |
c: class confidences,
|
| 26 |
l: predicted boxes,
|
|
@@ -51,7 +51,7 @@ class MultiBoxLoss(nn.Module):
|
|
| 51 |
priors shape: torch.size(num_priors,4)
|
| 52 |
|
| 53 |
ground_truth (tensor): Ground truth boxes and labels for a batch,
|
| 54 |
-
shape: [batch_size,num_objs,5] (last idx
|
| 55 |
"""
|
| 56 |
|
| 57 |
loc_data, conf_data, landm_data = predictions
|
|
|
|
| 19 |
(default negative:positive ratio 3:1)
|
| 20 |
Objective Loss:
|
| 21 |
L(x,c,l,g) = (Lconf(x, c) + αLloc(x,l,g)) / N
|
| 22 |
+
Where, Lconf==the CrossEntropy Loss and Lloc==the SmoothL1 Loss
|
| 23 |
+
weighted by α which==set to 1 by cross val.
|
| 24 |
Args:
|
| 25 |
c: class confidences,
|
| 26 |
l: predicted boxes,
|
|
|
|
| 51 |
priors shape: torch.size(num_priors,4)
|
| 52 |
|
| 53 |
ground_truth (tensor): Ground truth boxes and labels for a batch,
|
| 54 |
+
shape: [batch_size,num_objs,5] (last idx==the label).
|
| 55 |
"""
|
| 56 |
|
| 57 |
loc_data, conf_data, landm_data = predictions
|
retinaface/retinaface_detection.py
CHANGED
|
@@ -39,7 +39,7 @@ class RetinaFaceDetection(object):
|
|
| 39 |
return True
|
| 40 |
|
| 41 |
def remove_prefix(self, state_dict, prefix):
|
| 42 |
-
''' Old style model
|
| 43 |
f = lambda x: x.split(prefix, 1)[-1] if x.startswith(prefix) else x
|
| 44 |
return {f(key): value for key, value in state_dict.items()}
|
| 45 |
|
|
|
|
| 39 |
return True
|
| 40 |
|
| 41 |
def remove_prefix(self, state_dict, prefix):
|
| 42 |
+
''' Old style model==stored with all names of parameters sharing common prefix 'module.' '''
|
| 43 |
f = lambda x: x.split(prefix, 1)[-1] if x.startswith(prefix) else x
|
| 44 |
return {f(key): value for key, value in state_dict.items()}
|
| 45 |
|
retinaface/utils/box_utils.py
CHANGED
|
@@ -49,7 +49,7 @@ def intersect(box_a, box_b):
|
|
| 49 |
|
| 50 |
def jaccard(box_a, box_b):
|
| 51 |
"""Compute the jaccard overlap of two sets of boxes. The jaccard overlap
|
| 52 |
-
|
| 53 |
ground truth boxes and default boxes.
|
| 54 |
E.g.:
|
| 55 |
A ∩ B / A ∪ B = A ∩ B / (area(A) + area(B) - A ∩ B)
|
|
|
|
| 49 |
|
| 50 |
def jaccard(box_a, box_b):
|
| 51 |
"""Compute the jaccard overlap of two sets of boxes. The jaccard overlap
|
| 52 |
+
==simply the intersection over union of two boxes. Here we operate on
|
| 53 |
ground truth boxes and default boxes.
|
| 54 |
E.g.:
|
| 55 |
A ∩ B / A ∪ B = A ∩ B / (area(A) + area(B) - A ∩ B)
|