Spaces:
Running
on
Zero
Running
on
Zero
Upload 216 files
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- .gitattributes +10 -0
- src/pixel3dmm/preprocessing/PIPNet/FaceBoxesV2/detector.py +39 -0
- src/pixel3dmm/preprocessing/PIPNet/FaceBoxesV2/faceboxes_detector.py +97 -0
- src/pixel3dmm/preprocessing/PIPNet/FaceBoxesV2/utils/__init__.py +0 -0
- src/pixel3dmm/preprocessing/PIPNet/FaceBoxesV2/utils/box_utils.py +276 -0
- src/pixel3dmm/preprocessing/PIPNet/FaceBoxesV2/utils/build.py +57 -0
- src/pixel3dmm/preprocessing/PIPNet/FaceBoxesV2/utils/config.py +14 -0
- src/pixel3dmm/preprocessing/PIPNet/FaceBoxesV2/utils/faceboxes.py +239 -0
- src/pixel3dmm/preprocessing/PIPNet/FaceBoxesV2/utils/make.sh +3 -0
- src/pixel3dmm/preprocessing/PIPNet/FaceBoxesV2/utils/nms/__init__.py +0 -0
- src/pixel3dmm/preprocessing/PIPNet/FaceBoxesV2/utils/nms/__pycache__/__init__.cpython-36.pyc +0 -0
- src/pixel3dmm/preprocessing/PIPNet/FaceBoxesV2/utils/nms/__pycache__/__init__.cpython-37.pyc +0 -0
- src/pixel3dmm/preprocessing/PIPNet/FaceBoxesV2/utils/nms/__pycache__/__init__.cpython-38.pyc +0 -0
- src/pixel3dmm/preprocessing/PIPNet/FaceBoxesV2/utils/nms/cpu_nms.pyx +163 -0
- src/pixel3dmm/preprocessing/PIPNet/FaceBoxesV2/utils/nms/gpu_nms.hpp +2 -0
- src/pixel3dmm/preprocessing/PIPNet/FaceBoxesV2/utils/nms/gpu_nms.pyx +31 -0
- src/pixel3dmm/preprocessing/PIPNet/FaceBoxesV2/utils/nms/nms_kernel.cu +144 -0
- src/pixel3dmm/preprocessing/PIPNet/FaceBoxesV2/utils/nms/py_cpu_nms.py +38 -0
- src/pixel3dmm/preprocessing/PIPNet/FaceBoxesV2/utils/nms_wrapper.py +15 -0
- src/pixel3dmm/preprocessing/PIPNet/FaceBoxesV2/utils/prior_box.py +43 -0
- src/pixel3dmm/preprocessing/PIPNet/FaceBoxesV2/utils/timer.py +40 -0
- src/pixel3dmm/preprocessing/PIPNet/FaceBoxesV2/weights/FaceBoxesV2.pth +3 -0
- src/pixel3dmm/preprocessing/PIPNet/LICENSE +21 -0
- src/pixel3dmm/preprocessing/PIPNet/README.md +161 -0
- src/pixel3dmm/preprocessing/PIPNet/data/AFLW/meanface.txt +1 -0
- src/pixel3dmm/preprocessing/PIPNet/data/COFW/meanface.txt +1 -0
- src/pixel3dmm/preprocessing/PIPNet/data/LaPa/.gitkeep +1 -0
- src/pixel3dmm/preprocessing/PIPNet/data/LaPa/meanface.txt +1 -0
- src/pixel3dmm/preprocessing/PIPNet/data/WFLW/meanface.txt +1 -0
- src/pixel3dmm/preprocessing/PIPNet/data/data_300W/meanface.txt +1 -0
- src/pixel3dmm/preprocessing/PIPNet/data/data_300W_CELEBA/meanface.txt +1 -0
- src/pixel3dmm/preprocessing/PIPNet/data/data_300W_COFW_WFLW/meanface.txt +1 -0
- src/pixel3dmm/preprocessing/PIPNet/experiments/AFLW/__pycache__/pip_32_16_60_r101_l2_l1_10_1_nb10.cpython-37.pyc +0 -0
- src/pixel3dmm/preprocessing/PIPNet/experiments/AFLW/__pycache__/pip_32_16_60_r152_l2_l1_10_1_nb10.cpython-37.pyc +0 -0
- src/pixel3dmm/preprocessing/PIPNet/experiments/AFLW/__pycache__/pip_32_16_60_r18_focal_l1_01_1.cpython-37.pyc +0 -0
- src/pixel3dmm/preprocessing/PIPNet/experiments/AFLW/__pycache__/pip_32_16_60_r18_focal_l2_01_1.cpython-37.pyc +0 -0
- src/pixel3dmm/preprocessing/PIPNet/experiments/AFLW/__pycache__/pip_32_16_60_r18_l2_l1_10_1.cpython-37.pyc +0 -0
- src/pixel3dmm/preprocessing/PIPNet/experiments/AFLW/__pycache__/pip_32_16_60_r18_l2_l1_10_1_nb10.cpython-37.pyc +0 -0
- src/pixel3dmm/preprocessing/PIPNet/experiments/AFLW/__pycache__/pip_32_16_60_r18_l2_l1_10_1_nb2.cpython-37.pyc +0 -0
- src/pixel3dmm/preprocessing/PIPNet/experiments/AFLW/__pycache__/pip_32_16_60_r18_l2_l1_10_1_nb5.cpython-37.pyc +0 -0
- src/pixel3dmm/preprocessing/PIPNet/experiments/AFLW/__pycache__/pip_32_16_60_r18_l2_l2_10_1.cpython-37.pyc +0 -0
- src/pixel3dmm/preprocessing/PIPNet/experiments/AFLW/__pycache__/pip_32_16_60_r50_l2_l1_10_1.cpython-37.pyc +0 -0
- src/pixel3dmm/preprocessing/PIPNet/experiments/AFLW/__pycache__/pip_32_16_60_r50_l2_l1_10_1_nb10.cpython-37.pyc +0 -0
- src/pixel3dmm/preprocessing/PIPNet/experiments/AFLW/__pycache__/pip_32_16_60_r50_l2_l1_10_1_nb2.cpython-37.pyc +0 -0
- src/pixel3dmm/preprocessing/PIPNet/experiments/AFLW/__pycache__/pip_32_16_60_r50_l2_l1_10_1_nb5.cpython-37.pyc +0 -0
- src/pixel3dmm/preprocessing/PIPNet/experiments/AFLW/pip_32_16_60_r101_l2_l1_10_1_nb10.py +21 -0
- src/pixel3dmm/preprocessing/PIPNet/experiments/AFLW/pip_32_16_60_r18_l2_l1_10_1_nb10.py +21 -0
- src/pixel3dmm/preprocessing/PIPNet/experiments/AFLW/pip_32_16_60_r50_l2_l1_10_1_nb10.py +21 -0
- src/pixel3dmm/preprocessing/PIPNet/experiments/COFW/__pycache__/pip_32_16_60_r101_l2_l1_10_1_nb10.cpython-37.pyc +0 -0
- src/pixel3dmm/preprocessing/PIPNet/experiments/COFW/__pycache__/pip_32_16_60_r152_l2_l1_10_1_nb10.cpython-37.pyc +0 -0
.gitattributes
CHANGED
@@ -59,3 +59,13 @@ src/pixel3dmm/preprocessing/MICA/documents/LYHM.gif filter=lfs diff=lfs merge=lf
|
|
59 |
src/pixel3dmm/preprocessing/MICA/documents/STIRLING.gif filter=lfs diff=lfs merge=lfs -text
|
60 |
src/pixel3dmm/preprocessing/MICA/documents/teaser.jpg filter=lfs diff=lfs merge=lfs -text
|
61 |
src/pixel3dmm/preprocessing/MICA/documents/voxceleb.gif filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
59 |
src/pixel3dmm/preprocessing/MICA/documents/STIRLING.gif filter=lfs diff=lfs merge=lfs -text
|
60 |
src/pixel3dmm/preprocessing/MICA/documents/teaser.jpg filter=lfs diff=lfs merge=lfs -text
|
61 |
src/pixel3dmm/preprocessing/MICA/documents/voxceleb.gif filter=lfs diff=lfs merge=lfs -text
|
62 |
+
src/pixel3dmm/preprocessing/PIPNet/images/1_out_WFLW_model.jpg filter=lfs diff=lfs merge=lfs -text
|
63 |
+
src/pixel3dmm/preprocessing/PIPNet/images/1.jpg filter=lfs diff=lfs merge=lfs -text
|
64 |
+
src/pixel3dmm/preprocessing/PIPNet/images/2.jpg filter=lfs diff=lfs merge=lfs -text
|
65 |
+
src/pixel3dmm/preprocessing/PIPNet/images/3.jpg filter=lfs diff=lfs merge=lfs -text
|
66 |
+
src/pixel3dmm/preprocessing/PIPNet/images/speed.png filter=lfs diff=lfs merge=lfs -text
|
67 |
+
src/pixel3dmm/preprocessing/PIPNet/videos/002_out_WFLW_model.gif filter=lfs diff=lfs merge=lfs -text
|
68 |
+
src/pixel3dmm/preprocessing/PIPNet/videos/002.avi filter=lfs diff=lfs merge=lfs -text
|
69 |
+
src/pixel3dmm/preprocessing/PIPNet/videos/007_out_300W_CELEBA_model.gif filter=lfs diff=lfs merge=lfs -text
|
70 |
+
src/pixel3dmm/preprocessing/PIPNet/videos/007.avi filter=lfs diff=lfs merge=lfs -text
|
71 |
+
src/pixel3dmm/preprocessing/PIPNet/videos/shaolin_soccer.gif filter=lfs diff=lfs merge=lfs -text
|
src/pixel3dmm/preprocessing/PIPNet/FaceBoxesV2/detector.py
ADDED
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import cv2
|
2 |
+
|
3 |
+
class Detector(object):
|
4 |
+
def __init__(self, model_arch, model_weights):
|
5 |
+
self.model_arch = model_arch
|
6 |
+
self.model_weights = model_weights
|
7 |
+
|
8 |
+
def detect(self, image, thresh):
|
9 |
+
raise NotImplementedError
|
10 |
+
|
11 |
+
def crop(self, image, detections):
|
12 |
+
crops = []
|
13 |
+
for det in detections:
|
14 |
+
xmin = max(det[2], 0)
|
15 |
+
ymin = max(det[3], 0)
|
16 |
+
width = det[4]
|
17 |
+
height = det[5]
|
18 |
+
xmax = min(xmin+width, image.shape[1])
|
19 |
+
ymax = min(ymin+height, image.shape[0])
|
20 |
+
cut = image[ymin:ymax, xmin:xmax,:]
|
21 |
+
crops.append(cut)
|
22 |
+
|
23 |
+
return crops
|
24 |
+
|
25 |
+
def draw(self, image, detections, im_scale=None):
|
26 |
+
if im_scale is not None:
|
27 |
+
image = cv2.resize(image, None, None, fx=im_scale, fy=im_scale, interpolation=cv2.INTER_LINEAR)
|
28 |
+
detections = [[det[0],det[1],int(det[2]*im_scale),int(det[3]*im_scale),int(det[4]*im_scale),int(det[5]*im_scale)] for det in detections]
|
29 |
+
|
30 |
+
for det in detections:
|
31 |
+
xmin = det[2]
|
32 |
+
ymin = det[3]
|
33 |
+
width = det[4]
|
34 |
+
height = det[5]
|
35 |
+
xmax = xmin + width
|
36 |
+
ymax = ymin + height
|
37 |
+
cv2.rectangle(image, (xmin, ymin), (xmax, ymax), (0, 0, 255), 2)
|
38 |
+
|
39 |
+
return image
|
src/pixel3dmm/preprocessing/PIPNet/FaceBoxesV2/faceboxes_detector.py
ADDED
@@ -0,0 +1,97 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from detector import Detector
|
2 |
+
import cv2, os
|
3 |
+
import numpy as np
|
4 |
+
import torch
|
5 |
+
import torch.nn as nn
|
6 |
+
from utils.config import cfg
|
7 |
+
from utils.prior_box import PriorBox
|
8 |
+
from utils.nms_wrapper import nms
|
9 |
+
from utils.faceboxes import FaceBoxesV2
|
10 |
+
from utils.box_utils import decode
|
11 |
+
import time
|
12 |
+
|
13 |
+
class FaceBoxesDetector(Detector):
|
14 |
+
def __init__(self, model_arch, model_weights, use_gpu, device):
|
15 |
+
super().__init__(model_arch, model_weights)
|
16 |
+
self.name = 'FaceBoxesDetector'
|
17 |
+
self.net = FaceBoxesV2(phase='test', size=None, num_classes=2) # initialize detector
|
18 |
+
self.use_gpu = use_gpu
|
19 |
+
self.device = device
|
20 |
+
|
21 |
+
state_dict = torch.load(self.model_weights, map_location=self.device)
|
22 |
+
# create new OrderedDict that does not contain `module.`
|
23 |
+
from collections import OrderedDict
|
24 |
+
new_state_dict = OrderedDict()
|
25 |
+
for k, v in state_dict.items():
|
26 |
+
name = k[7:] # remove `module.`
|
27 |
+
new_state_dict[name] = v
|
28 |
+
# load params
|
29 |
+
self.net.load_state_dict(new_state_dict)
|
30 |
+
self.net = self.net.to(self.device)
|
31 |
+
self.net.eval()
|
32 |
+
|
33 |
+
|
34 |
+
def detect(self, image, thresh=0.6, im_scale=None):
|
35 |
+
# auto resize for large images
|
36 |
+
if im_scale is None:
|
37 |
+
height, width, _ = image.shape
|
38 |
+
if min(height, width) > 600:
|
39 |
+
im_scale = 600. / min(height, width)
|
40 |
+
else:
|
41 |
+
im_scale = 1
|
42 |
+
image_scale = cv2.resize(image, None, None, fx=im_scale, fy=im_scale, interpolation=cv2.INTER_LINEAR)
|
43 |
+
|
44 |
+
scale = torch.Tensor([image_scale.shape[1], image_scale.shape[0], image_scale.shape[1], image_scale.shape[0]])
|
45 |
+
image_scale = torch.from_numpy(image_scale.transpose(2,0,1)).to(self.device).int()
|
46 |
+
mean_tmp = torch.IntTensor([104, 117, 123]).to(self.device)
|
47 |
+
mean_tmp = mean_tmp.unsqueeze(1).unsqueeze(2)
|
48 |
+
image_scale -= mean_tmp
|
49 |
+
image_scale = image_scale.float().unsqueeze(0)
|
50 |
+
scale = scale.to(self.device)
|
51 |
+
|
52 |
+
with torch.no_grad():
|
53 |
+
out = self.net(image_scale)
|
54 |
+
#priorbox = PriorBox(cfg, out[2], (image_scale.size()[2], image_scale.size()[3]), phase='test')
|
55 |
+
priorbox = PriorBox(cfg, image_size=(image_scale.size()[2], image_scale.size()[3]))
|
56 |
+
priors = priorbox.forward()
|
57 |
+
priors = priors.to(self.device)
|
58 |
+
loc, conf = out
|
59 |
+
prior_data = priors.data
|
60 |
+
boxes = decode(loc.data.squeeze(0), prior_data, cfg['variance'])
|
61 |
+
boxes = boxes * scale
|
62 |
+
boxes = boxes.cpu().numpy()
|
63 |
+
scores = conf.data.cpu().numpy()[:, 1]
|
64 |
+
|
65 |
+
# ignore low scores
|
66 |
+
inds = np.where(scores > thresh)[0]
|
67 |
+
boxes = boxes[inds]
|
68 |
+
scores = scores[inds]
|
69 |
+
|
70 |
+
# keep top-K before NMS
|
71 |
+
order = scores.argsort()[::-1][:5000]
|
72 |
+
boxes = boxes[order]
|
73 |
+
scores = scores[order]
|
74 |
+
|
75 |
+
# do NMS
|
76 |
+
dets = np.hstack((boxes, scores[:, np.newaxis])).astype(np.float32, copy=False)
|
77 |
+
keep = nms(dets, 0.3)
|
78 |
+
dets = dets[keep, :]
|
79 |
+
|
80 |
+
dets = dets[:750, :]
|
81 |
+
detections_scale = []
|
82 |
+
for i in range(dets.shape[0]):
|
83 |
+
xmin = int(dets[i][0])
|
84 |
+
ymin = int(dets[i][1])
|
85 |
+
xmax = int(dets[i][2])
|
86 |
+
ymax = int(dets[i][3])
|
87 |
+
score = dets[i][4]
|
88 |
+
width = xmax - xmin
|
89 |
+
height = ymax - ymin
|
90 |
+
detections_scale.append(['face', score, xmin, ymin, width, height])
|
91 |
+
|
92 |
+
# adapt bboxes to the original image size
|
93 |
+
if len(detections_scale) > 0:
|
94 |
+
detections_scale = [[det[0],det[1],int(det[2]/im_scale),int(det[3]/im_scale),int(det[4]/im_scale),int(det[5]/im_scale)] for det in detections_scale]
|
95 |
+
|
96 |
+
return detections_scale, im_scale
|
97 |
+
|
src/pixel3dmm/preprocessing/PIPNet/FaceBoxesV2/utils/__init__.py
ADDED
File without changes
|
src/pixel3dmm/preprocessing/PIPNet/FaceBoxesV2/utils/box_utils.py
ADDED
@@ -0,0 +1,276 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import torch
|
2 |
+
import numpy as np
|
3 |
+
|
4 |
+
|
5 |
+
def point_form(boxes):
|
6 |
+
""" Convert prior_boxes to (xmin, ymin, xmax, ymax)
|
7 |
+
representation for comparison to point form ground truth data.
|
8 |
+
Args:
|
9 |
+
boxes: (tensor) center-size default boxes from priorbox layers.
|
10 |
+
Return:
|
11 |
+
boxes: (tensor) Converted xmin, ymin, xmax, ymax form of boxes.
|
12 |
+
"""
|
13 |
+
return torch.cat((boxes[:, :2] - boxes[:, 2:]/2, # xmin, ymin
|
14 |
+
boxes[:, :2] + boxes[:, 2:]/2), 1) # xmax, ymax
|
15 |
+
|
16 |
+
|
17 |
+
def center_size(boxes):
|
18 |
+
""" Convert prior_boxes to (cx, cy, w, h)
|
19 |
+
representation for comparison to center-size form ground truth data.
|
20 |
+
Args:
|
21 |
+
boxes: (tensor) point_form boxes
|
22 |
+
Return:
|
23 |
+
boxes: (tensor) Converted xmin, ymin, xmax, ymax form of boxes.
|
24 |
+
"""
|
25 |
+
return torch.cat((boxes[:, 2:] + boxes[:, :2])/2, # cx, cy
|
26 |
+
boxes[:, 2:] - boxes[:, :2], 1) # w, h
|
27 |
+
|
28 |
+
|
29 |
+
def intersect(box_a, box_b):
|
30 |
+
""" We resize both tensors to [A,B,2] without new malloc:
|
31 |
+
[A,2] -> [A,1,2] -> [A,B,2]
|
32 |
+
[B,2] -> [1,B,2] -> [A,B,2]
|
33 |
+
Then we compute the area of intersect between box_a and box_b.
|
34 |
+
Args:
|
35 |
+
box_a: (tensor) bounding boxes, Shape: [A,4].
|
36 |
+
box_b: (tensor) bounding boxes, Shape: [B,4].
|
37 |
+
Return:
|
38 |
+
(tensor) intersection area, Shape: [A,B].
|
39 |
+
"""
|
40 |
+
A = box_a.size(0)
|
41 |
+
B = box_b.size(0)
|
42 |
+
max_xy = torch.min(box_a[:, 2:].unsqueeze(1).expand(A, B, 2),
|
43 |
+
box_b[:, 2:].unsqueeze(0).expand(A, B, 2))
|
44 |
+
min_xy = torch.max(box_a[:, :2].unsqueeze(1).expand(A, B, 2),
|
45 |
+
box_b[:, :2].unsqueeze(0).expand(A, B, 2))
|
46 |
+
inter = torch.clamp((max_xy - min_xy), min=0)
|
47 |
+
return inter[:, :, 0] * inter[:, :, 1]
|
48 |
+
|
49 |
+
|
50 |
+
def jaccard(box_a, box_b):
|
51 |
+
"""Compute the jaccard overlap of two sets of boxes. The jaccard overlap
|
52 |
+
is 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)
|
56 |
+
Args:
|
57 |
+
box_a: (tensor) Ground truth bounding boxes, Shape: [num_objects,4]
|
58 |
+
box_b: (tensor) Prior boxes from priorbox layers, Shape: [num_priors,4]
|
59 |
+
Return:
|
60 |
+
jaccard overlap: (tensor) Shape: [box_a.size(0), box_b.size(0)]
|
61 |
+
"""
|
62 |
+
inter = intersect(box_a, box_b)
|
63 |
+
area_a = ((box_a[:, 2]-box_a[:, 0]) *
|
64 |
+
(box_a[:, 3]-box_a[:, 1])).unsqueeze(1).expand_as(inter) # [A,B]
|
65 |
+
area_b = ((box_b[:, 2]-box_b[:, 0]) *
|
66 |
+
(box_b[:, 3]-box_b[:, 1])).unsqueeze(0).expand_as(inter) # [A,B]
|
67 |
+
union = area_a + area_b - inter
|
68 |
+
return inter / union # [A,B]
|
69 |
+
|
70 |
+
|
71 |
+
def matrix_iou(a, b):
|
72 |
+
"""
|
73 |
+
return iou of a and b, numpy version for data augenmentation
|
74 |
+
"""
|
75 |
+
lt = np.maximum(a[:, np.newaxis, :2], b[:, :2])
|
76 |
+
rb = np.minimum(a[:, np.newaxis, 2:], b[:, 2:])
|
77 |
+
|
78 |
+
area_i = np.prod(rb - lt, axis=2) * (lt < rb).all(axis=2)
|
79 |
+
area_a = np.prod(a[:, 2:] - a[:, :2], axis=1)
|
80 |
+
area_b = np.prod(b[:, 2:] - b[:, :2], axis=1)
|
81 |
+
return area_i / (area_a[:, np.newaxis] + area_b - area_i)
|
82 |
+
|
83 |
+
|
84 |
+
def matrix_iof(a, b):
|
85 |
+
"""
|
86 |
+
return iof of a and b, numpy version for data augenmentation
|
87 |
+
"""
|
88 |
+
lt = np.maximum(a[:, np.newaxis, :2], b[:, :2])
|
89 |
+
rb = np.minimum(a[:, np.newaxis, 2:], b[:, 2:])
|
90 |
+
|
91 |
+
area_i = np.prod(rb - lt, axis=2) * (lt < rb).all(axis=2)
|
92 |
+
area_a = np.prod(a[:, 2:] - a[:, :2], axis=1)
|
93 |
+
return area_i / np.maximum(area_a[:, np.newaxis], 1)
|
94 |
+
|
95 |
+
|
96 |
+
def match(threshold, truths, priors, variances, labels, loc_t, conf_t, idx):
|
97 |
+
"""Match each prior box with the ground truth box of the highest jaccard
|
98 |
+
overlap, encode the bounding boxes, then return the matched indices
|
99 |
+
corresponding to both confidence and location preds.
|
100 |
+
Args:
|
101 |
+
threshold: (float) The overlap threshold used when mathing boxes.
|
102 |
+
truths: (tensor) Ground truth boxes, Shape: [num_obj, num_priors].
|
103 |
+
priors: (tensor) Prior boxes from priorbox layers, Shape: [n_priors,4].
|
104 |
+
variances: (tensor) Variances corresponding to each prior coord,
|
105 |
+
Shape: [num_priors, 4].
|
106 |
+
labels: (tensor) All the class labels for the image, Shape: [num_obj].
|
107 |
+
loc_t: (tensor) Tensor to be filled w/ endcoded location targets.
|
108 |
+
conf_t: (tensor) Tensor to be filled w/ matched indices for conf preds.
|
109 |
+
idx: (int) current batch index
|
110 |
+
Return:
|
111 |
+
The matched indices corresponding to 1)location and 2)confidence preds.
|
112 |
+
"""
|
113 |
+
# jaccard index
|
114 |
+
overlaps = jaccard(
|
115 |
+
truths,
|
116 |
+
point_form(priors)
|
117 |
+
)
|
118 |
+
# (Bipartite Matching)
|
119 |
+
# [1,num_objects] best prior for each ground truth
|
120 |
+
best_prior_overlap, best_prior_idx = overlaps.max(1, keepdim=True)
|
121 |
+
|
122 |
+
# ignore hard gt
|
123 |
+
valid_gt_idx = best_prior_overlap[:, 0] >= 0.2
|
124 |
+
best_prior_idx_filter = best_prior_idx[valid_gt_idx, :]
|
125 |
+
if best_prior_idx_filter.shape[0] <= 0:
|
126 |
+
loc_t[idx] = 0
|
127 |
+
conf_t[idx] = 0
|
128 |
+
return
|
129 |
+
|
130 |
+
# [1,num_priors] best ground truth for each prior
|
131 |
+
best_truth_overlap, best_truth_idx = overlaps.max(0, keepdim=True)
|
132 |
+
best_truth_idx.squeeze_(0)
|
133 |
+
best_truth_overlap.squeeze_(0)
|
134 |
+
best_prior_idx.squeeze_(1)
|
135 |
+
best_prior_idx_filter.squeeze_(1)
|
136 |
+
best_prior_overlap.squeeze_(1)
|
137 |
+
best_truth_overlap.index_fill_(0, best_prior_idx_filter, 2) # ensure best prior
|
138 |
+
# TODO refactor: index best_prior_idx with long tensor
|
139 |
+
# ensure every gt matches with its prior of max overlap
|
140 |
+
for j in range(best_prior_idx.size(0)):
|
141 |
+
best_truth_idx[best_prior_idx[j]] = j
|
142 |
+
matches = truths[best_truth_idx] # Shape: [num_priors,4]
|
143 |
+
conf = labels[best_truth_idx] # Shape: [num_priors]
|
144 |
+
conf[best_truth_overlap < threshold] = 0 # label as background
|
145 |
+
loc = encode(matches, priors, variances)
|
146 |
+
loc_t[idx] = loc # [num_priors,4] encoded offsets to learn
|
147 |
+
conf_t[idx] = conf # [num_priors] top class label for each prior
|
148 |
+
|
149 |
+
|
150 |
+
def encode(matched, priors, variances):
|
151 |
+
"""Encode the variances from the priorbox layers into the ground truth boxes
|
152 |
+
we have matched (based on jaccard overlap) with the prior boxes.
|
153 |
+
Args:
|
154 |
+
matched: (tensor) Coords of ground truth for each prior in point-form
|
155 |
+
Shape: [num_priors, 4].
|
156 |
+
priors: (tensor) Prior boxes in center-offset form
|
157 |
+
Shape: [num_priors,4].
|
158 |
+
variances: (list[float]) Variances of priorboxes
|
159 |
+
Return:
|
160 |
+
encoded boxes (tensor), Shape: [num_priors, 4]
|
161 |
+
"""
|
162 |
+
|
163 |
+
# dist b/t match center and prior's center
|
164 |
+
g_cxcy = (matched[:, :2] + matched[:, 2:])/2 - priors[:, :2]
|
165 |
+
# encode variance
|
166 |
+
g_cxcy /= (variances[0] * priors[:, 2:])
|
167 |
+
# match wh / prior wh
|
168 |
+
g_wh = (matched[:, 2:] - matched[:, :2]) / priors[:, 2:]
|
169 |
+
g_wh = torch.log(g_wh) / variances[1]
|
170 |
+
# return target for smooth_l1_loss
|
171 |
+
return torch.cat([g_cxcy, g_wh], 1) # [num_priors,4]
|
172 |
+
|
173 |
+
|
174 |
+
# Adapted from https://github.com/Hakuyume/chainer-ssd
|
175 |
+
def decode(loc, priors, variances):
|
176 |
+
"""Decode locations from predictions using priors to undo
|
177 |
+
the encoding we did for offset regression at train time.
|
178 |
+
Args:
|
179 |
+
loc (tensor): location predictions for loc layers,
|
180 |
+
Shape: [num_priors,4]
|
181 |
+
priors (tensor): Prior boxes in center-offset form.
|
182 |
+
Shape: [num_priors,4].
|
183 |
+
variances: (list[float]) Variances of priorboxes
|
184 |
+
Return:
|
185 |
+
decoded bounding box predictions
|
186 |
+
"""
|
187 |
+
|
188 |
+
boxes = torch.cat((
|
189 |
+
priors[:, :2] + loc[:, :2] * variances[0] * priors[:, 2:],
|
190 |
+
priors[:, 2:] * torch.exp(loc[:, 2:] * variances[1])), 1)
|
191 |
+
boxes[:, :2] -= boxes[:, 2:] / 2
|
192 |
+
boxes[:, 2:] += boxes[:, :2]
|
193 |
+
return boxes
|
194 |
+
|
195 |
+
|
196 |
+
def log_sum_exp(x):
|
197 |
+
"""Utility function for computing log_sum_exp while determining
|
198 |
+
This will be used to determine unaveraged confidence loss across
|
199 |
+
all examples in a batch.
|
200 |
+
Args:
|
201 |
+
x (Variable(tensor)): conf_preds from conf layers
|
202 |
+
"""
|
203 |
+
x_max = x.data.max()
|
204 |
+
return torch.log(torch.sum(torch.exp(x-x_max), 1, keepdim=True)) + x_max
|
205 |
+
|
206 |
+
|
207 |
+
# Original author: Francisco Massa:
|
208 |
+
# https://github.com/fmassa/object-detection.torch
|
209 |
+
# Ported to PyTorch by Max deGroot (02/01/2017)
|
210 |
+
def nms(boxes, scores, overlap=0.5, top_k=200):
|
211 |
+
"""Apply non-maximum suppression at test time to avoid detecting too many
|
212 |
+
overlapping bounding boxes for a given object.
|
213 |
+
Args:
|
214 |
+
boxes: (tensor) The location preds for the img, Shape: [num_priors,4].
|
215 |
+
scores: (tensor) The class predscores for the img, Shape:[num_priors].
|
216 |
+
overlap: (float) The overlap thresh for suppressing unnecessary boxes.
|
217 |
+
top_k: (int) The Maximum number of box preds to consider.
|
218 |
+
Return:
|
219 |
+
The indices of the kept boxes with respect to num_priors.
|
220 |
+
"""
|
221 |
+
|
222 |
+
keep = torch.Tensor(scores.size(0)).fill_(0).long()
|
223 |
+
if boxes.numel() == 0:
|
224 |
+
return keep
|
225 |
+
x1 = boxes[:, 0]
|
226 |
+
y1 = boxes[:, 1]
|
227 |
+
x2 = boxes[:, 2]
|
228 |
+
y2 = boxes[:, 3]
|
229 |
+
area = torch.mul(x2 - x1, y2 - y1)
|
230 |
+
v, idx = scores.sort(0) # sort in ascending order
|
231 |
+
# I = I[v >= 0.01]
|
232 |
+
idx = idx[-top_k:] # indices of the top-k largest vals
|
233 |
+
xx1 = boxes.new()
|
234 |
+
yy1 = boxes.new()
|
235 |
+
xx2 = boxes.new()
|
236 |
+
yy2 = boxes.new()
|
237 |
+
w = boxes.new()
|
238 |
+
h = boxes.new()
|
239 |
+
|
240 |
+
# keep = torch.Tensor()
|
241 |
+
count = 0
|
242 |
+
while idx.numel() > 0:
|
243 |
+
i = idx[-1] # index of current largest val
|
244 |
+
# keep.append(i)
|
245 |
+
keep[count] = i
|
246 |
+
count += 1
|
247 |
+
if idx.size(0) == 1:
|
248 |
+
break
|
249 |
+
idx = idx[:-1] # remove kept element from view
|
250 |
+
# load bboxes of next highest vals
|
251 |
+
torch.index_select(x1, 0, idx, out=xx1)
|
252 |
+
torch.index_select(y1, 0, idx, out=yy1)
|
253 |
+
torch.index_select(x2, 0, idx, out=xx2)
|
254 |
+
torch.index_select(y2, 0, idx, out=yy2)
|
255 |
+
# store element-wise max with next highest score
|
256 |
+
xx1 = torch.clamp(xx1, min=x1[i])
|
257 |
+
yy1 = torch.clamp(yy1, min=y1[i])
|
258 |
+
xx2 = torch.clamp(xx2, max=x2[i])
|
259 |
+
yy2 = torch.clamp(yy2, max=y2[i])
|
260 |
+
w.resize_as_(xx2)
|
261 |
+
h.resize_as_(yy2)
|
262 |
+
w = xx2 - xx1
|
263 |
+
h = yy2 - yy1
|
264 |
+
# check sizes of xx1 and xx2.. after each iteration
|
265 |
+
w = torch.clamp(w, min=0.0)
|
266 |
+
h = torch.clamp(h, min=0.0)
|
267 |
+
inter = w*h
|
268 |
+
# IoU = i / (area(a) + area(b) - i)
|
269 |
+
rem_areas = torch.index_select(area, 0, idx) # load remaining areas)
|
270 |
+
union = (rem_areas - inter) + area[i]
|
271 |
+
IoU = inter/union # store result in iou
|
272 |
+
# keep only elements with an IoU <= overlap
|
273 |
+
idx = idx[IoU.le(overlap)]
|
274 |
+
return keep, count
|
275 |
+
|
276 |
+
|
src/pixel3dmm/preprocessing/PIPNet/FaceBoxesV2/utils/build.py
ADDED
@@ -0,0 +1,57 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# coding: utf-8
|
2 |
+
|
3 |
+
# --------------------------------------------------------
|
4 |
+
# Fast R-CNN
|
5 |
+
# Copyright (c) 2015 Microsoft
|
6 |
+
# Licensed under The MIT License [see LICENSE for details]
|
7 |
+
# Written by Ross Girshick
|
8 |
+
# --------------------------------------------------------
|
9 |
+
|
10 |
+
import os
|
11 |
+
from os.path import join as pjoin
|
12 |
+
import numpy as np
|
13 |
+
from distutils.core import setup
|
14 |
+
from distutils.extension import Extension
|
15 |
+
from Cython.Distutils import build_ext
|
16 |
+
|
17 |
+
|
18 |
+
def find_in_path(name, path):
|
19 |
+
"Find a file in a search path"
|
20 |
+
# adapted fom http://code.activestate.com/recipes/52224-find-a-file-given-a-search-path/
|
21 |
+
for dir in path.split(os.pathsep):
|
22 |
+
binpath = pjoin(dir, name)
|
23 |
+
if os.path.exists(binpath):
|
24 |
+
return os.path.abspath(binpath)
|
25 |
+
return None
|
26 |
+
|
27 |
+
|
28 |
+
# Obtain the numpy include directory. This logic works across numpy versions.
|
29 |
+
try:
|
30 |
+
numpy_include = np.get_include()
|
31 |
+
except AttributeError:
|
32 |
+
numpy_include = np.get_numpy_include()
|
33 |
+
|
34 |
+
|
35 |
+
# run the customize_compiler
|
36 |
+
class custom_build_ext(build_ext):
|
37 |
+
def build_extensions(self):
|
38 |
+
# customize_compiler_for_nvcc(self.compiler)
|
39 |
+
build_ext.build_extensions(self)
|
40 |
+
|
41 |
+
|
42 |
+
ext_modules = [
|
43 |
+
Extension(
|
44 |
+
"nms.cpu_nms",
|
45 |
+
["nms/cpu_nms.pyx"],
|
46 |
+
# extra_compile_args={'gcc': ["-Wno-cpp", "-Wno-unused-function"]},
|
47 |
+
extra_compile_args=["-Wno-cpp", "-Wno-unused-function"],
|
48 |
+
include_dirs=[numpy_include]
|
49 |
+
)
|
50 |
+
]
|
51 |
+
|
52 |
+
setup(
|
53 |
+
name='mot_utils',
|
54 |
+
ext_modules=ext_modules,
|
55 |
+
# inject our custom trigger
|
56 |
+
cmdclass={'build_ext': custom_build_ext},
|
57 |
+
)
|
src/pixel3dmm/preprocessing/PIPNet/FaceBoxesV2/utils/config.py
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# config.py
|
2 |
+
|
3 |
+
cfg = {
|
4 |
+
'name': 'FaceBoxes',
|
5 |
+
#'min_dim': 1024,
|
6 |
+
#'feature_maps': [[32, 32], [16, 16], [8, 8]],
|
7 |
+
# 'aspect_ratios': [[1], [1], [1]],
|
8 |
+
'min_sizes': [[32, 64, 128], [256], [512]],
|
9 |
+
'steps': [32, 64, 128],
|
10 |
+
'variance': [0.1, 0.2],
|
11 |
+
'clip': False,
|
12 |
+
'loc_weight': 2.0,
|
13 |
+
'gpu_train': True
|
14 |
+
}
|
src/pixel3dmm/preprocessing/PIPNet/FaceBoxesV2/utils/faceboxes.py
ADDED
@@ -0,0 +1,239 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import torch
|
2 |
+
import torch.nn as nn
|
3 |
+
import torch.nn.functional as F
|
4 |
+
|
5 |
+
|
6 |
+
class BasicConv2d(nn.Module):
|
7 |
+
|
8 |
+
def __init__(self, in_channels, out_channels, **kwargs):
|
9 |
+
super(BasicConv2d, self).__init__()
|
10 |
+
self.conv = nn.Conv2d(in_channels, out_channels, bias=False, **kwargs)
|
11 |
+
self.bn = nn.BatchNorm2d(out_channels, eps=1e-5)
|
12 |
+
|
13 |
+
def forward(self, x):
|
14 |
+
x = self.conv(x)
|
15 |
+
x = self.bn(x)
|
16 |
+
return F.relu(x, inplace=True)
|
17 |
+
|
18 |
+
|
19 |
+
class Inception(nn.Module):
|
20 |
+
|
21 |
+
def __init__(self):
|
22 |
+
super(Inception, self).__init__()
|
23 |
+
self.branch1x1 = BasicConv2d(128, 32, kernel_size=1, padding=0)
|
24 |
+
self.branch1x1_2 = BasicConv2d(128, 32, kernel_size=1, padding=0)
|
25 |
+
self.branch3x3_reduce = BasicConv2d(128, 24, kernel_size=1, padding=0)
|
26 |
+
self.branch3x3 = BasicConv2d(24, 32, kernel_size=3, padding=1)
|
27 |
+
self.branch3x3_reduce_2 = BasicConv2d(128, 24, kernel_size=1, padding=0)
|
28 |
+
self.branch3x3_2 = BasicConv2d(24, 32, kernel_size=3, padding=1)
|
29 |
+
self.branch3x3_3 = BasicConv2d(32, 32, kernel_size=3, padding=1)
|
30 |
+
|
31 |
+
def forward(self, x):
|
32 |
+
branch1x1 = self.branch1x1(x)
|
33 |
+
|
34 |
+
branch1x1_pool = F.avg_pool2d(x, kernel_size=3, stride=1, padding=1)
|
35 |
+
branch1x1_2 = self.branch1x1_2(branch1x1_pool)
|
36 |
+
|
37 |
+
branch3x3_reduce = self.branch3x3_reduce(x)
|
38 |
+
branch3x3 = self.branch3x3(branch3x3_reduce)
|
39 |
+
|
40 |
+
branch3x3_reduce_2 = self.branch3x3_reduce_2(x)
|
41 |
+
branch3x3_2 = self.branch3x3_2(branch3x3_reduce_2)
|
42 |
+
branch3x3_3 = self.branch3x3_3(branch3x3_2)
|
43 |
+
|
44 |
+
outputs = [branch1x1, branch1x1_2, branch3x3, branch3x3_3]
|
45 |
+
return torch.cat(outputs, 1)
|
46 |
+
|
47 |
+
|
48 |
+
class CRelu(nn.Module):
|
49 |
+
|
50 |
+
def __init__(self, in_channels, out_channels, **kwargs):
|
51 |
+
super(CRelu, self).__init__()
|
52 |
+
self.conv = nn.Conv2d(in_channels, out_channels, bias=False, **kwargs)
|
53 |
+
self.bn = nn.BatchNorm2d(out_channels, eps=1e-5)
|
54 |
+
|
55 |
+
def forward(self, x):
|
56 |
+
x = self.conv(x)
|
57 |
+
x = self.bn(x)
|
58 |
+
x = torch.cat([x, -x], 1)
|
59 |
+
x = F.relu(x, inplace=True)
|
60 |
+
return x
|
61 |
+
|
62 |
+
|
63 |
+
class FaceBoxes(nn.Module):
|
64 |
+
|
65 |
+
def __init__(self, phase, size, num_classes):
|
66 |
+
super(FaceBoxes, self).__init__()
|
67 |
+
self.phase = phase
|
68 |
+
self.num_classes = num_classes
|
69 |
+
self.size = size
|
70 |
+
|
71 |
+
self.conv1 = CRelu(3, 24, kernel_size=7, stride=4, padding=3)
|
72 |
+
self.conv2 = CRelu(48, 64, kernel_size=5, stride=2, padding=2)
|
73 |
+
|
74 |
+
self.inception1 = Inception()
|
75 |
+
self.inception2 = Inception()
|
76 |
+
self.inception3 = Inception()
|
77 |
+
|
78 |
+
self.conv3_1 = BasicConv2d(128, 128, kernel_size=1, stride=1, padding=0)
|
79 |
+
self.conv3_2 = BasicConv2d(128, 256, kernel_size=3, stride=2, padding=1)
|
80 |
+
|
81 |
+
self.conv4_1 = BasicConv2d(256, 128, kernel_size=1, stride=1, padding=0)
|
82 |
+
self.conv4_2 = BasicConv2d(128, 256, kernel_size=3, stride=2, padding=1)
|
83 |
+
|
84 |
+
self.loc, self.conf = self.multibox(self.num_classes)
|
85 |
+
|
86 |
+
if self.phase == 'test':
|
87 |
+
self.softmax = nn.Softmax(dim=-1)
|
88 |
+
|
89 |
+
if self.phase == 'train':
|
90 |
+
for m in self.modules():
|
91 |
+
if isinstance(m, nn.Conv2d):
|
92 |
+
if m.bias is not None:
|
93 |
+
nn.init.xavier_normal_(m.weight.data)
|
94 |
+
m.bias.data.fill_(0.02)
|
95 |
+
else:
|
96 |
+
m.weight.data.normal_(0, 0.01)
|
97 |
+
elif isinstance(m, nn.BatchNorm2d):
|
98 |
+
m.weight.data.fill_(1)
|
99 |
+
m.bias.data.zero_()
|
100 |
+
|
101 |
+
def multibox(self, num_classes):
|
102 |
+
loc_layers = []
|
103 |
+
conf_layers = []
|
104 |
+
loc_layers += [nn.Conv2d(128, 21 * 4, kernel_size=3, padding=1)]
|
105 |
+
conf_layers += [nn.Conv2d(128, 21 * num_classes, kernel_size=3, padding=1)]
|
106 |
+
loc_layers += [nn.Conv2d(256, 1 * 4, kernel_size=3, padding=1)]
|
107 |
+
conf_layers += [nn.Conv2d(256, 1 * num_classes, kernel_size=3, padding=1)]
|
108 |
+
loc_layers += [nn.Conv2d(256, 1 * 4, kernel_size=3, padding=1)]
|
109 |
+
conf_layers += [nn.Conv2d(256, 1 * num_classes, kernel_size=3, padding=1)]
|
110 |
+
return nn.Sequential(*loc_layers), nn.Sequential(*conf_layers)
|
111 |
+
|
112 |
+
def forward(self, x):
|
113 |
+
|
114 |
+
detection_sources = list()
|
115 |
+
loc = list()
|
116 |
+
conf = list()
|
117 |
+
|
118 |
+
x = self.conv1(x)
|
119 |
+
x = F.max_pool2d(x, kernel_size=3, stride=2, padding=1)
|
120 |
+
x = self.conv2(x)
|
121 |
+
x = F.max_pool2d(x, kernel_size=3, stride=2, padding=1)
|
122 |
+
x = self.inception1(x)
|
123 |
+
x = self.inception2(x)
|
124 |
+
x = self.inception3(x)
|
125 |
+
detection_sources.append(x)
|
126 |
+
|
127 |
+
x = self.conv3_1(x)
|
128 |
+
x = self.conv3_2(x)
|
129 |
+
detection_sources.append(x)
|
130 |
+
|
131 |
+
x = self.conv4_1(x)
|
132 |
+
x = self.conv4_2(x)
|
133 |
+
detection_sources.append(x)
|
134 |
+
|
135 |
+
for (x, l, c) in zip(detection_sources, self.loc, self.conf):
|
136 |
+
loc.append(l(x).permute(0, 2, 3, 1).contiguous())
|
137 |
+
conf.append(c(x).permute(0, 2, 3, 1).contiguous())
|
138 |
+
|
139 |
+
loc = torch.cat([o.view(o.size(0), -1) for o in loc], 1)
|
140 |
+
conf = torch.cat([o.view(o.size(0), -1) for o in conf], 1)
|
141 |
+
|
142 |
+
if self.phase == "test":
|
143 |
+
output = (loc.view(loc.size(0), -1, 4),
|
144 |
+
self.softmax(conf.view(conf.size(0), -1, self.num_classes)))
|
145 |
+
else:
|
146 |
+
output = (loc.view(loc.size(0), -1, 4),
|
147 |
+
conf.view(conf.size(0), -1, self.num_classes))
|
148 |
+
|
149 |
+
return output
|
150 |
+
|
151 |
+
class FaceBoxesV2(nn.Module):
|
152 |
+
|
153 |
+
def __init__(self, phase, size, num_classes):
|
154 |
+
super(FaceBoxesV2, self).__init__()
|
155 |
+
self.phase = phase
|
156 |
+
self.num_classes = num_classes
|
157 |
+
self.size = size
|
158 |
+
|
159 |
+
self.conv1 = BasicConv2d(3, 8, kernel_size=3, stride=2, padding=1)
|
160 |
+
self.conv2 = BasicConv2d(8, 16, kernel_size=3, stride=2, padding=1)
|
161 |
+
self.conv3 = BasicConv2d(16, 32, kernel_size=3, stride=2, padding=1)
|
162 |
+
self.conv4 = BasicConv2d(32, 64, kernel_size=3, stride=2, padding=1)
|
163 |
+
self.conv5 = BasicConv2d(64, 128, kernel_size=3, stride=2, padding=1)
|
164 |
+
|
165 |
+
self.inception1 = Inception()
|
166 |
+
self.inception2 = Inception()
|
167 |
+
self.inception3 = Inception()
|
168 |
+
|
169 |
+
self.conv6_1 = BasicConv2d(128, 128, kernel_size=1, stride=1, padding=0)
|
170 |
+
self.conv6_2 = BasicConv2d(128, 256, kernel_size=3, stride=2, padding=1)
|
171 |
+
|
172 |
+
self.conv7_1 = BasicConv2d(256, 128, kernel_size=1, stride=1, padding=0)
|
173 |
+
self.conv7_2 = BasicConv2d(128, 256, kernel_size=3, stride=2, padding=1)
|
174 |
+
|
175 |
+
self.loc, self.conf = self.multibox(self.num_classes)
|
176 |
+
|
177 |
+
if self.phase == 'test':
|
178 |
+
self.softmax = nn.Softmax(dim=-1)
|
179 |
+
|
180 |
+
if self.phase == 'train':
|
181 |
+
for m in self.modules():
|
182 |
+
if isinstance(m, nn.Conv2d):
|
183 |
+
if m.bias is not None:
|
184 |
+
nn.init.xavier_normal_(m.weight.data)
|
185 |
+
m.bias.data.fill_(0.02)
|
186 |
+
else:
|
187 |
+
m.weight.data.normal_(0, 0.01)
|
188 |
+
elif isinstance(m, nn.BatchNorm2d):
|
189 |
+
m.weight.data.fill_(1)
|
190 |
+
m.bias.data.zero_()
|
191 |
+
|
192 |
+
def multibox(self, num_classes):
|
193 |
+
loc_layers = []
|
194 |
+
conf_layers = []
|
195 |
+
loc_layers += [nn.Conv2d(128, 21 * 4, kernel_size=3, padding=1)]
|
196 |
+
conf_layers += [nn.Conv2d(128, 21 * num_classes, kernel_size=3, padding=1)]
|
197 |
+
loc_layers += [nn.Conv2d(256, 1 * 4, kernel_size=3, padding=1)]
|
198 |
+
conf_layers += [nn.Conv2d(256, 1 * num_classes, kernel_size=3, padding=1)]
|
199 |
+
loc_layers += [nn.Conv2d(256, 1 * 4, kernel_size=3, padding=1)]
|
200 |
+
conf_layers += [nn.Conv2d(256, 1 * num_classes, kernel_size=3, padding=1)]
|
201 |
+
return nn.Sequential(*loc_layers), nn.Sequential(*conf_layers)
|
202 |
+
|
203 |
+
def forward(self, x):
|
204 |
+
|
205 |
+
sources = list()
|
206 |
+
loc = list()
|
207 |
+
conf = list()
|
208 |
+
|
209 |
+
x = self.conv1(x)
|
210 |
+
x = self.conv2(x)
|
211 |
+
x = self.conv3(x)
|
212 |
+
x = self.conv4(x)
|
213 |
+
x = self.conv5(x)
|
214 |
+
x = self.inception1(x)
|
215 |
+
x = self.inception2(x)
|
216 |
+
x = self.inception3(x)
|
217 |
+
sources.append(x)
|
218 |
+
x = self.conv6_1(x)
|
219 |
+
x = self.conv6_2(x)
|
220 |
+
sources.append(x)
|
221 |
+
x = self.conv7_1(x)
|
222 |
+
x = self.conv7_2(x)
|
223 |
+
sources.append(x)
|
224 |
+
|
225 |
+
for (x, l, c) in zip(sources, self.loc, self.conf):
|
226 |
+
loc.append(l(x).permute(0, 2, 3, 1).contiguous())
|
227 |
+
conf.append(c(x).permute(0, 2, 3, 1).contiguous())
|
228 |
+
|
229 |
+
loc = torch.cat([o.view(o.size(0), -1) for o in loc], 1)
|
230 |
+
conf = torch.cat([o.view(o.size(0), -1) for o in conf], 1)
|
231 |
+
|
232 |
+
if self.phase == "test":
|
233 |
+
output = (loc.view(loc.size(0), -1, 4),
|
234 |
+
self.softmax(conf.view(-1, self.num_classes)))
|
235 |
+
else:
|
236 |
+
output = (loc.view(loc.size(0), -1, 4),
|
237 |
+
conf.view(conf.size(0), -1, self.num_classes))
|
238 |
+
|
239 |
+
return output
|
src/pixel3dmm/preprocessing/PIPNet/FaceBoxesV2/utils/make.sh
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/env bash
|
2 |
+
python3 build.py build_ext --inplace
|
3 |
+
|
src/pixel3dmm/preprocessing/PIPNet/FaceBoxesV2/utils/nms/__init__.py
ADDED
File without changes
|
src/pixel3dmm/preprocessing/PIPNet/FaceBoxesV2/utils/nms/__pycache__/__init__.cpython-36.pyc
ADDED
Binary file (116 Bytes). View file
|
|
src/pixel3dmm/preprocessing/PIPNet/FaceBoxesV2/utils/nms/__pycache__/__init__.cpython-37.pyc
ADDED
Binary file (120 Bytes). View file
|
|
src/pixel3dmm/preprocessing/PIPNet/FaceBoxesV2/utils/nms/__pycache__/__init__.cpython-38.pyc
ADDED
Binary file (181 Bytes). View file
|
|
src/pixel3dmm/preprocessing/PIPNet/FaceBoxesV2/utils/nms/cpu_nms.pyx
ADDED
@@ -0,0 +1,163 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# --------------------------------------------------------
|
2 |
+
# Fast R-CNN
|
3 |
+
# Copyright (c) 2015 Microsoft
|
4 |
+
# Licensed under The MIT License [see LICENSE for details]
|
5 |
+
# Written by Ross Girshick
|
6 |
+
# --------------------------------------------------------
|
7 |
+
|
8 |
+
import numpy as np
|
9 |
+
cimport numpy as np
|
10 |
+
|
11 |
+
cdef inline np.float32_t max(np.float32_t a, np.float32_t b):
|
12 |
+
return a if a >= b else b
|
13 |
+
|
14 |
+
cdef inline np.float32_t min(np.float32_t a, np.float32_t b):
|
15 |
+
return a if a <= b else b
|
16 |
+
|
17 |
+
def cpu_nms(np.ndarray[np.float32_t, ndim=2] dets, np.float thresh):
|
18 |
+
cdef np.ndarray[np.float32_t, ndim=1] x1 = dets[:, 0]
|
19 |
+
cdef np.ndarray[np.float32_t, ndim=1] y1 = dets[:, 1]
|
20 |
+
cdef np.ndarray[np.float32_t, ndim=1] x2 = dets[:, 2]
|
21 |
+
cdef np.ndarray[np.float32_t, ndim=1] y2 = dets[:, 3]
|
22 |
+
cdef np.ndarray[np.float32_t, ndim=1] scores = dets[:, 4]
|
23 |
+
|
24 |
+
cdef np.ndarray[np.float32_t, ndim=1] areas = (x2 - x1 + 1) * (y2 - y1 + 1)
|
25 |
+
cdef np.ndarray[np.int_t, ndim=1] order = scores.argsort()[::-1]
|
26 |
+
|
27 |
+
cdef int ndets = dets.shape[0]
|
28 |
+
cdef np.ndarray[np.int_t, ndim=1] suppressed = \
|
29 |
+
np.zeros((ndets), dtype=np.int)
|
30 |
+
|
31 |
+
# nominal indices
|
32 |
+
cdef int _i, _j
|
33 |
+
# sorted indices
|
34 |
+
cdef int i, j
|
35 |
+
# temp variables for box i's (the box currently under consideration)
|
36 |
+
cdef np.float32_t ix1, iy1, ix2, iy2, iarea
|
37 |
+
# variables for computing overlap with box j (lower scoring box)
|
38 |
+
cdef np.float32_t xx1, yy1, xx2, yy2
|
39 |
+
cdef np.float32_t w, h
|
40 |
+
cdef np.float32_t inter, ovr
|
41 |
+
|
42 |
+
keep = []
|
43 |
+
for _i in range(ndets):
|
44 |
+
i = order[_i]
|
45 |
+
if suppressed[i] == 1:
|
46 |
+
continue
|
47 |
+
keep.append(i)
|
48 |
+
ix1 = x1[i]
|
49 |
+
iy1 = y1[i]
|
50 |
+
ix2 = x2[i]
|
51 |
+
iy2 = y2[i]
|
52 |
+
iarea = areas[i]
|
53 |
+
for _j in range(_i + 1, ndets):
|
54 |
+
j = order[_j]
|
55 |
+
if suppressed[j] == 1:
|
56 |
+
continue
|
57 |
+
xx1 = max(ix1, x1[j])
|
58 |
+
yy1 = max(iy1, y1[j])
|
59 |
+
xx2 = min(ix2, x2[j])
|
60 |
+
yy2 = min(iy2, y2[j])
|
61 |
+
w = max(0.0, xx2 - xx1 + 1)
|
62 |
+
h = max(0.0, yy2 - yy1 + 1)
|
63 |
+
inter = w * h
|
64 |
+
ovr = inter / (iarea + areas[j] - inter)
|
65 |
+
if ovr >= thresh:
|
66 |
+
suppressed[j] = 1
|
67 |
+
|
68 |
+
return keep
|
69 |
+
|
70 |
+
def cpu_soft_nms(np.ndarray[float, ndim=2] boxes, float sigma=0.5, float Nt=0.3, float threshold=0.001, unsigned int method=0):
|
71 |
+
cdef unsigned int N = boxes.shape[0]
|
72 |
+
cdef float iw, ih, box_area
|
73 |
+
cdef float ua
|
74 |
+
cdef int pos = 0
|
75 |
+
cdef float maxscore = 0
|
76 |
+
cdef int maxpos = 0
|
77 |
+
cdef float x1,x2,y1,y2,tx1,tx2,ty1,ty2,ts,area,weight,ov
|
78 |
+
|
79 |
+
for i in range(N):
|
80 |
+
maxscore = boxes[i, 4]
|
81 |
+
maxpos = i
|
82 |
+
|
83 |
+
tx1 = boxes[i,0]
|
84 |
+
ty1 = boxes[i,1]
|
85 |
+
tx2 = boxes[i,2]
|
86 |
+
ty2 = boxes[i,3]
|
87 |
+
ts = boxes[i,4]
|
88 |
+
|
89 |
+
pos = i + 1
|
90 |
+
# get max box
|
91 |
+
while pos < N:
|
92 |
+
if maxscore < boxes[pos, 4]:
|
93 |
+
maxscore = boxes[pos, 4]
|
94 |
+
maxpos = pos
|
95 |
+
pos = pos + 1
|
96 |
+
|
97 |
+
# add max box as a detection
|
98 |
+
boxes[i,0] = boxes[maxpos,0]
|
99 |
+
boxes[i,1] = boxes[maxpos,1]
|
100 |
+
boxes[i,2] = boxes[maxpos,2]
|
101 |
+
boxes[i,3] = boxes[maxpos,3]
|
102 |
+
boxes[i,4] = boxes[maxpos,4]
|
103 |
+
|
104 |
+
# swap ith box with position of max box
|
105 |
+
boxes[maxpos,0] = tx1
|
106 |
+
boxes[maxpos,1] = ty1
|
107 |
+
boxes[maxpos,2] = tx2
|
108 |
+
boxes[maxpos,3] = ty2
|
109 |
+
boxes[maxpos,4] = ts
|
110 |
+
|
111 |
+
tx1 = boxes[i,0]
|
112 |
+
ty1 = boxes[i,1]
|
113 |
+
tx2 = boxes[i,2]
|
114 |
+
ty2 = boxes[i,3]
|
115 |
+
ts = boxes[i,4]
|
116 |
+
|
117 |
+
pos = i + 1
|
118 |
+
# NMS iterations, note that N changes if detection boxes fall below threshold
|
119 |
+
while pos < N:
|
120 |
+
x1 = boxes[pos, 0]
|
121 |
+
y1 = boxes[pos, 1]
|
122 |
+
x2 = boxes[pos, 2]
|
123 |
+
y2 = boxes[pos, 3]
|
124 |
+
s = boxes[pos, 4]
|
125 |
+
|
126 |
+
area = (x2 - x1 + 1) * (y2 - y1 + 1)
|
127 |
+
iw = (min(tx2, x2) - max(tx1, x1) + 1)
|
128 |
+
if iw > 0:
|
129 |
+
ih = (min(ty2, y2) - max(ty1, y1) + 1)
|
130 |
+
if ih > 0:
|
131 |
+
ua = float((tx2 - tx1 + 1) * (ty2 - ty1 + 1) + area - iw * ih)
|
132 |
+
ov = iw * ih / ua #iou between max box and detection box
|
133 |
+
|
134 |
+
if method == 1: # linear
|
135 |
+
if ov > Nt:
|
136 |
+
weight = 1 - ov
|
137 |
+
else:
|
138 |
+
weight = 1
|
139 |
+
elif method == 2: # gaussian
|
140 |
+
weight = np.exp(-(ov * ov)/sigma)
|
141 |
+
else: # original NMS
|
142 |
+
if ov > Nt:
|
143 |
+
weight = 0
|
144 |
+
else:
|
145 |
+
weight = 1
|
146 |
+
|
147 |
+
boxes[pos, 4] = weight*boxes[pos, 4]
|
148 |
+
|
149 |
+
# if box score falls below threshold, discard the box by swapping with last box
|
150 |
+
# update N
|
151 |
+
if boxes[pos, 4] < threshold:
|
152 |
+
boxes[pos,0] = boxes[N-1, 0]
|
153 |
+
boxes[pos,1] = boxes[N-1, 1]
|
154 |
+
boxes[pos,2] = boxes[N-1, 2]
|
155 |
+
boxes[pos,3] = boxes[N-1, 3]
|
156 |
+
boxes[pos,4] = boxes[N-1, 4]
|
157 |
+
N = N - 1
|
158 |
+
pos = pos - 1
|
159 |
+
|
160 |
+
pos = pos + 1
|
161 |
+
|
162 |
+
keep = [i for i in range(N)]
|
163 |
+
return keep
|
src/pixel3dmm/preprocessing/PIPNet/FaceBoxesV2/utils/nms/gpu_nms.hpp
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
1 |
+
void _nms(int* keep_out, int* num_out, const float* boxes_host, int boxes_num,
|
2 |
+
int boxes_dim, float nms_overlap_thresh, int device_id);
|
src/pixel3dmm/preprocessing/PIPNet/FaceBoxesV2/utils/nms/gpu_nms.pyx
ADDED
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# --------------------------------------------------------
|
2 |
+
# Faster R-CNN
|
3 |
+
# Copyright (c) 2015 Microsoft
|
4 |
+
# Licensed under The MIT License [see LICENSE for details]
|
5 |
+
# Written by Ross Girshick
|
6 |
+
# --------------------------------------------------------
|
7 |
+
|
8 |
+
import numpy as np
|
9 |
+
cimport numpy as np
|
10 |
+
|
11 |
+
assert sizeof(int) == sizeof(np.int32_t)
|
12 |
+
|
13 |
+
cdef extern from "gpu_nms.hpp":
|
14 |
+
void _nms(np.int32_t*, int*, np.float32_t*, int, int, float, int)
|
15 |
+
|
16 |
+
def gpu_nms(np.ndarray[np.float32_t, ndim=2] dets, np.float thresh,
|
17 |
+
np.int32_t device_id=0):
|
18 |
+
cdef int boxes_num = dets.shape[0]
|
19 |
+
cdef int boxes_dim = dets.shape[1]
|
20 |
+
cdef int num_out
|
21 |
+
cdef np.ndarray[np.int32_t, ndim=1] \
|
22 |
+
keep = np.zeros(boxes_num, dtype=np.int32)
|
23 |
+
cdef np.ndarray[np.float32_t, ndim=1] \
|
24 |
+
scores = dets[:, 4]
|
25 |
+
cdef np.ndarray[np.int_t, ndim=1] \
|
26 |
+
order = scores.argsort()[::-1]
|
27 |
+
cdef np.ndarray[np.float32_t, ndim=2] \
|
28 |
+
sorted_dets = dets[order, :]
|
29 |
+
_nms(&keep[0], &num_out, &sorted_dets[0, 0], boxes_num, boxes_dim, thresh, device_id)
|
30 |
+
keep = keep[:num_out]
|
31 |
+
return list(order[keep])
|
src/pixel3dmm/preprocessing/PIPNet/FaceBoxesV2/utils/nms/nms_kernel.cu
ADDED
@@ -0,0 +1,144 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// ------------------------------------------------------------------
|
2 |
+
// Faster R-CNN
|
3 |
+
// Copyright (c) 2015 Microsoft
|
4 |
+
// Licensed under The MIT License [see fast-rcnn/LICENSE for details]
|
5 |
+
// Written by Shaoqing Ren
|
6 |
+
// ------------------------------------------------------------------
|
7 |
+
|
8 |
+
#include "gpu_nms.hpp"
|
9 |
+
#include <vector>
|
10 |
+
#include <iostream>
|
11 |
+
|
12 |
+
#define CUDA_CHECK(condition) \
|
13 |
+
/* Code block avoids redefinition of cudaError_t error */ \
|
14 |
+
do { \
|
15 |
+
cudaError_t error = condition; \
|
16 |
+
if (error != cudaSuccess) { \
|
17 |
+
std::cout << cudaGetErrorString(error) << std::endl; \
|
18 |
+
} \
|
19 |
+
} while (0)
|
20 |
+
|
21 |
+
#define DIVUP(m,n) ((m) / (n) + ((m) % (n) > 0))
|
22 |
+
int const threadsPerBlock = sizeof(unsigned long long) * 8;
|
23 |
+
|
24 |
+
__device__ inline float devIoU(float const * const a, float const * const b) {
|
25 |
+
float left = max(a[0], b[0]), right = min(a[2], b[2]);
|
26 |
+
float top = max(a[1], b[1]), bottom = min(a[3], b[3]);
|
27 |
+
float width = max(right - left + 1, 0.f), height = max(bottom - top + 1, 0.f);
|
28 |
+
float interS = width * height;
|
29 |
+
float Sa = (a[2] - a[0] + 1) * (a[3] - a[1] + 1);
|
30 |
+
float Sb = (b[2] - b[0] + 1) * (b[3] - b[1] + 1);
|
31 |
+
return interS / (Sa + Sb - interS);
|
32 |
+
}
|
33 |
+
|
34 |
+
__global__ void nms_kernel(const int n_boxes, const float nms_overlap_thresh,
|
35 |
+
const float *dev_boxes, unsigned long long *dev_mask) {
|
36 |
+
const int row_start = blockIdx.y;
|
37 |
+
const int col_start = blockIdx.x;
|
38 |
+
|
39 |
+
// if (row_start > col_start) return;
|
40 |
+
|
41 |
+
const int row_size =
|
42 |
+
min(n_boxes - row_start * threadsPerBlock, threadsPerBlock);
|
43 |
+
const int col_size =
|
44 |
+
min(n_boxes - col_start * threadsPerBlock, threadsPerBlock);
|
45 |
+
|
46 |
+
__shared__ float block_boxes[threadsPerBlock * 5];
|
47 |
+
if (threadIdx.x < col_size) {
|
48 |
+
block_boxes[threadIdx.x * 5 + 0] =
|
49 |
+
dev_boxes[(threadsPerBlock * col_start + threadIdx.x) * 5 + 0];
|
50 |
+
block_boxes[threadIdx.x * 5 + 1] =
|
51 |
+
dev_boxes[(threadsPerBlock * col_start + threadIdx.x) * 5 + 1];
|
52 |
+
block_boxes[threadIdx.x * 5 + 2] =
|
53 |
+
dev_boxes[(threadsPerBlock * col_start + threadIdx.x) * 5 + 2];
|
54 |
+
block_boxes[threadIdx.x * 5 + 3] =
|
55 |
+
dev_boxes[(threadsPerBlock * col_start + threadIdx.x) * 5 + 3];
|
56 |
+
block_boxes[threadIdx.x * 5 + 4] =
|
57 |
+
dev_boxes[(threadsPerBlock * col_start + threadIdx.x) * 5 + 4];
|
58 |
+
}
|
59 |
+
__syncthreads();
|
60 |
+
|
61 |
+
if (threadIdx.x < row_size) {
|
62 |
+
const int cur_box_idx = threadsPerBlock * row_start + threadIdx.x;
|
63 |
+
const float *cur_box = dev_boxes + cur_box_idx * 5;
|
64 |
+
int i = 0;
|
65 |
+
unsigned long long t = 0;
|
66 |
+
int start = 0;
|
67 |
+
if (row_start == col_start) {
|
68 |
+
start = threadIdx.x + 1;
|
69 |
+
}
|
70 |
+
for (i = start; i < col_size; i++) {
|
71 |
+
if (devIoU(cur_box, block_boxes + i * 5) > nms_overlap_thresh) {
|
72 |
+
t |= 1ULL << i;
|
73 |
+
}
|
74 |
+
}
|
75 |
+
const int col_blocks = DIVUP(n_boxes, threadsPerBlock);
|
76 |
+
dev_mask[cur_box_idx * col_blocks + col_start] = t;
|
77 |
+
}
|
78 |
+
}
|
79 |
+
|
80 |
+
void _set_device(int device_id) {
|
81 |
+
int current_device;
|
82 |
+
CUDA_CHECK(cudaGetDevice(¤t_device));
|
83 |
+
if (current_device == device_id) {
|
84 |
+
return;
|
85 |
+
}
|
86 |
+
// The call to cudaSetDevice must come before any calls to Get, which
|
87 |
+
// may perform initialization using the GPU.
|
88 |
+
CUDA_CHECK(cudaSetDevice(device_id));
|
89 |
+
}
|
90 |
+
|
91 |
+
void _nms(int* keep_out, int* num_out, const float* boxes_host, int boxes_num,
|
92 |
+
int boxes_dim, float nms_overlap_thresh, int device_id) {
|
93 |
+
_set_device(device_id);
|
94 |
+
|
95 |
+
float* boxes_dev = NULL;
|
96 |
+
unsigned long long* mask_dev = NULL;
|
97 |
+
|
98 |
+
const int col_blocks = DIVUP(boxes_num, threadsPerBlock);
|
99 |
+
|
100 |
+
CUDA_CHECK(cudaMalloc(&boxes_dev,
|
101 |
+
boxes_num * boxes_dim * sizeof(float)));
|
102 |
+
CUDA_CHECK(cudaMemcpy(boxes_dev,
|
103 |
+
boxes_host,
|
104 |
+
boxes_num * boxes_dim * sizeof(float),
|
105 |
+
cudaMemcpyHostToDevice));
|
106 |
+
|
107 |
+
CUDA_CHECK(cudaMalloc(&mask_dev,
|
108 |
+
boxes_num * col_blocks * sizeof(unsigned long long)));
|
109 |
+
|
110 |
+
dim3 blocks(DIVUP(boxes_num, threadsPerBlock),
|
111 |
+
DIVUP(boxes_num, threadsPerBlock));
|
112 |
+
dim3 threads(threadsPerBlock);
|
113 |
+
nms_kernel<<<blocks, threads>>>(boxes_num,
|
114 |
+
nms_overlap_thresh,
|
115 |
+
boxes_dev,
|
116 |
+
mask_dev);
|
117 |
+
|
118 |
+
std::vector<unsigned long long> mask_host(boxes_num * col_blocks);
|
119 |
+
CUDA_CHECK(cudaMemcpy(&mask_host[0],
|
120 |
+
mask_dev,
|
121 |
+
sizeof(unsigned long long) * boxes_num * col_blocks,
|
122 |
+
cudaMemcpyDeviceToHost));
|
123 |
+
|
124 |
+
std::vector<unsigned long long> remv(col_blocks);
|
125 |
+
memset(&remv[0], 0, sizeof(unsigned long long) * col_blocks);
|
126 |
+
|
127 |
+
int num_to_keep = 0;
|
128 |
+
for (int i = 0; i < boxes_num; i++) {
|
129 |
+
int nblock = i / threadsPerBlock;
|
130 |
+
int inblock = i % threadsPerBlock;
|
131 |
+
|
132 |
+
if (!(remv[nblock] & (1ULL << inblock))) {
|
133 |
+
keep_out[num_to_keep++] = i;
|
134 |
+
unsigned long long *p = &mask_host[0] + i * col_blocks;
|
135 |
+
for (int j = nblock; j < col_blocks; j++) {
|
136 |
+
remv[j] |= p[j];
|
137 |
+
}
|
138 |
+
}
|
139 |
+
}
|
140 |
+
*num_out = num_to_keep;
|
141 |
+
|
142 |
+
CUDA_CHECK(cudaFree(boxes_dev));
|
143 |
+
CUDA_CHECK(cudaFree(mask_dev));
|
144 |
+
}
|
src/pixel3dmm/preprocessing/PIPNet/FaceBoxesV2/utils/nms/py_cpu_nms.py
ADDED
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# --------------------------------------------------------
|
2 |
+
# Fast R-CNN
|
3 |
+
# Copyright (c) 2015 Microsoft
|
4 |
+
# Licensed under The MIT License [see LICENSE for details]
|
5 |
+
# Written by Ross Girshick
|
6 |
+
# --------------------------------------------------------
|
7 |
+
|
8 |
+
import numpy as np
|
9 |
+
|
10 |
+
def py_cpu_nms(dets, thresh):
|
11 |
+
"""Pure Python NMS baseline."""
|
12 |
+
x1 = dets[:, 0]
|
13 |
+
y1 = dets[:, 1]
|
14 |
+
x2 = dets[:, 2]
|
15 |
+
y2 = dets[:, 3]
|
16 |
+
scores = dets[:, 4]
|
17 |
+
|
18 |
+
areas = (x2 - x1 + 1) * (y2 - y1 + 1)
|
19 |
+
order = scores.argsort()[::-1]
|
20 |
+
|
21 |
+
keep = []
|
22 |
+
while order.size > 0:
|
23 |
+
i = order[0]
|
24 |
+
keep.append(i)
|
25 |
+
xx1 = np.maximum(x1[i], x1[order[1:]])
|
26 |
+
yy1 = np.maximum(y1[i], y1[order[1:]])
|
27 |
+
xx2 = np.minimum(x2[i], x2[order[1:]])
|
28 |
+
yy2 = np.minimum(y2[i], y2[order[1:]])
|
29 |
+
|
30 |
+
w = np.maximum(0.0, xx2 - xx1 + 1)
|
31 |
+
h = np.maximum(0.0, yy2 - yy1 + 1)
|
32 |
+
inter = w * h
|
33 |
+
ovr = inter / (areas[i] + areas[order[1:]] - inter)
|
34 |
+
|
35 |
+
inds = np.where(ovr <= thresh)[0]
|
36 |
+
order = order[inds + 1]
|
37 |
+
|
38 |
+
return keep
|
src/pixel3dmm/preprocessing/PIPNet/FaceBoxesV2/utils/nms_wrapper.py
ADDED
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# --------------------------------------------------------
|
2 |
+
# Fast R-CNN
|
3 |
+
# Copyright (c) 2015 Microsoft
|
4 |
+
# Licensed under The MIT License [see LICENSE for details]
|
5 |
+
# Written by Ross Girshick
|
6 |
+
# --------------------------------------------------------
|
7 |
+
|
8 |
+
from .nms.cpu_nms import cpu_nms, cpu_soft_nms
|
9 |
+
|
10 |
+
def nms(dets, thresh):
|
11 |
+
"""Dispatch to either CPU or GPU NMS implementations."""
|
12 |
+
|
13 |
+
if dets.shape[0] == 0:
|
14 |
+
return []
|
15 |
+
return cpu_nms(dets, thresh)
|
src/pixel3dmm/preprocessing/PIPNet/FaceBoxesV2/utils/prior_box.py
ADDED
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import torch
|
2 |
+
from itertools import product as product
|
3 |
+
import numpy as np
|
4 |
+
from math import ceil
|
5 |
+
|
6 |
+
|
7 |
+
class PriorBox(object):
|
8 |
+
def __init__(self, cfg, image_size=None, phase='train'):
|
9 |
+
super(PriorBox, self).__init__()
|
10 |
+
#self.aspect_ratios = cfg['aspect_ratios']
|
11 |
+
self.min_sizes = cfg['min_sizes']
|
12 |
+
self.steps = cfg['steps']
|
13 |
+
self.clip = cfg['clip']
|
14 |
+
self.image_size = image_size
|
15 |
+
self.feature_maps = [[ceil(self.image_size[0]/step), ceil(self.image_size[1]/step)] for step in self.steps]
|
16 |
+
|
17 |
+
def forward(self):
|
18 |
+
anchors = []
|
19 |
+
for k, f in enumerate(self.feature_maps):
|
20 |
+
min_sizes = self.min_sizes[k]
|
21 |
+
for i, j in product(range(f[0]), range(f[1])):
|
22 |
+
for min_size in min_sizes:
|
23 |
+
s_kx = min_size / self.image_size[1]
|
24 |
+
s_ky = min_size / self.image_size[0]
|
25 |
+
if min_size == 32:
|
26 |
+
dense_cx = [x*self.steps[k]/self.image_size[1] for x in [j+0, j+0.25, j+0.5, j+0.75]]
|
27 |
+
dense_cy = [y*self.steps[k]/self.image_size[0] for y in [i+0, i+0.25, i+0.5, i+0.75]]
|
28 |
+
for cy, cx in product(dense_cy, dense_cx):
|
29 |
+
anchors += [cx, cy, s_kx, s_ky]
|
30 |
+
elif min_size == 64:
|
31 |
+
dense_cx = [x*self.steps[k]/self.image_size[1] for x in [j+0, j+0.5]]
|
32 |
+
dense_cy = [y*self.steps[k]/self.image_size[0] for y in [i+0, i+0.5]]
|
33 |
+
for cy, cx in product(dense_cy, dense_cx):
|
34 |
+
anchors += [cx, cy, s_kx, s_ky]
|
35 |
+
else:
|
36 |
+
cx = (j + 0.5) * self.steps[k] / self.image_size[1]
|
37 |
+
cy = (i + 0.5) * self.steps[k] / self.image_size[0]
|
38 |
+
anchors += [cx, cy, s_kx, s_ky]
|
39 |
+
# back to torch land
|
40 |
+
output = torch.Tensor(anchors).view(-1, 4)
|
41 |
+
if self.clip:
|
42 |
+
output.clamp_(max=1, min=0)
|
43 |
+
return output
|
src/pixel3dmm/preprocessing/PIPNet/FaceBoxesV2/utils/timer.py
ADDED
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# --------------------------------------------------------
|
2 |
+
# Fast R-CNN
|
3 |
+
# Copyright (c) 2015 Microsoft
|
4 |
+
# Licensed under The MIT License [see LICENSE for details]
|
5 |
+
# Written by Ross Girshick
|
6 |
+
# --------------------------------------------------------
|
7 |
+
|
8 |
+
import time
|
9 |
+
|
10 |
+
|
11 |
+
class Timer(object):
|
12 |
+
"""A simple timer."""
|
13 |
+
def __init__(self):
|
14 |
+
self.total_time = 0.
|
15 |
+
self.calls = 0
|
16 |
+
self.start_time = 0.
|
17 |
+
self.diff = 0.
|
18 |
+
self.average_time = 0.
|
19 |
+
|
20 |
+
def tic(self):
|
21 |
+
# using time.time instead of time.clock because time time.clock
|
22 |
+
# does not normalize for multithreading
|
23 |
+
self.start_time = time.time()
|
24 |
+
|
25 |
+
def toc(self, average=True):
|
26 |
+
self.diff = time.time() - self.start_time
|
27 |
+
self.total_time += self.diff
|
28 |
+
self.calls += 1
|
29 |
+
self.average_time = self.total_time / self.calls
|
30 |
+
if average:
|
31 |
+
return self.average_time
|
32 |
+
else:
|
33 |
+
return self.diff
|
34 |
+
|
35 |
+
def clear(self):
|
36 |
+
self.total_time = 0.
|
37 |
+
self.calls = 0
|
38 |
+
self.start_time = 0.
|
39 |
+
self.diff = 0.
|
40 |
+
self.average_time = 0.
|
src/pixel3dmm/preprocessing/PIPNet/FaceBoxesV2/weights/FaceBoxesV2.pth
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:aae07fec4b62ac655508c06336662538803407852312ca5009fd93fb487d8cd7
|
3 |
+
size 4153573
|
src/pixel3dmm/preprocessing/PIPNet/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
MIT License
|
2 |
+
|
3 |
+
Copyright (c) 2020 Haibo Jin
|
4 |
+
|
5 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6 |
+
of this software and associated documentation files (the "Software"), to deal
|
7 |
+
in the Software without restriction, including without limitation the rights
|
8 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9 |
+
copies of the Software, and to permit persons to whom the Software is
|
10 |
+
furnished to do so, subject to the following conditions:
|
11 |
+
|
12 |
+
The above copyright notice and this permission notice shall be included in all
|
13 |
+
copies or substantial portions of the Software.
|
14 |
+
|
15 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21 |
+
SOFTWARE.
|
src/pixel3dmm/preprocessing/PIPNet/README.md
ADDED
@@ -0,0 +1,161 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Pixel-in-Pixel Net: Towards Efficient Facial Landmark Detection in the Wild
|
2 |
+
## Introduction
|
3 |
+
This is the code of paper [Pixel-in-Pixel Net: Towards Efficient Facial Landmark Detection in the Wild](https://arxiv.org/abs/2003.03771). We propose a novel facial landmark detector, PIPNet, that is **fast**, **accurate**, and **robust**. PIPNet can be trained under two settings: (1) supervised learning; (2) generalizable semi-supervised learning (GSSL). With GSSL, PIPNet has better cross-domain generalization performance by utilizing massive amounts of unlabeled data across domains.
|
4 |
+
|
5 |
+
<img src="images/speed.png" alt="speed" width="640px">
|
6 |
+
Figure 1. Comparison to existing methods on speed-accuracy tradeoff, tested on WFLW full test set (closer to bottom-right corner is better).<br><br>
|
7 |
+
|
8 |
+
<img src="images/detection_heads.png" alt="det_heads" width="512px">
|
9 |
+
Figure 2. Comparison of different detection heads.<br>
|
10 |
+
|
11 |
+
## Installation
|
12 |
+
1. Install Python3 and PyTorch >= v1.1
|
13 |
+
2. Clone this repository.
|
14 |
+
```Shell
|
15 |
+
git clone https://github.com/jhb86253817/PIPNet.git
|
16 |
+
```
|
17 |
+
3. Install the dependencies in requirements.txt.
|
18 |
+
```Shell
|
19 |
+
pip install -r requirements.txt
|
20 |
+
```
|
21 |
+
|
22 |
+
## Demo
|
23 |
+
1. We use a [modified version](https://github.com/jhb86253817/FaceBoxesV2) of [FaceBoxes](https://github.com/zisianw/FaceBoxes.PyTorch) as the face detector, so go to folder `FaceBoxesV2/utils`, run `sh make.sh` to build for NMS.
|
24 |
+
2. Back to folder `PIPNet`, create two empty folders `logs` and `snapshots`. For PIPNets, you can download our trained models from [here](https://drive.google.com/drive/folders/17OwDgJUfuc5_ymQ3QruD8pUnh5zHreP2?usp=sharing), and put them under folder `snapshots/DATA_NAME/EXPERIMENT_NAME/`.
|
25 |
+
3. Edit `run_demo.sh` to choose the config file and input source you want, then run `sh run_demo.sh`. We support image, video, and camera as the input. Some sample predictions can be seen as follows.
|
26 |
+
* PIPNet-ResNet18 trained on WFLW, with image `images/1.jpg` as the input:
|
27 |
+
<img src="images/1_out_WFLW_model.jpg" alt="1_out_WFLW_model" width="400px">
|
28 |
+
|
29 |
+
* PIPNet-ResNet18 trained on WFLW, with a snippet from *Shaolin Soccer* as the input:
|
30 |
+
<img src="videos/shaolin_soccer.gif" alt="shaolin_soccer" width="400px">
|
31 |
+
|
32 |
+
* PIPNet-ResNet18 trained on WFLW, with video `videos/002.avi` as the input:
|
33 |
+
<img src="videos/002_out_WFLW_model.gif" alt="002_out_WFLW_model" width="512px">
|
34 |
+
|
35 |
+
* PIPNet-ResNet18 trained on 300W+CelebA (GSSL), with video `videos/007.avi` as the input:
|
36 |
+
<img src="videos/007_out_300W_CELEBA_model.gif" alt="007_out_300W_CELEBA_model" width="512px">
|
37 |
+
|
38 |
+
## Training
|
39 |
+
|
40 |
+
### Supervised Learning
|
41 |
+
Datasets: [300W](https://ibug.doc.ic.ac.uk/resources/facial-point-annotations/), [COFW](http://www.vision.caltech.edu/xpburgos/ICCV13/), [WFLW](https://wywu.github.io/projects/LAB/WFLW.html), [AFLW](https://www.tugraz.at/institute/icg/research/team-bischof/lrs/downloads/aflw/), [LaPa](https://github.com/JDAI-CV/lapa-dataset)
|
42 |
+
|
43 |
+
1. Download the datasets from official sources, then put them under folder `data`. The folder structure should look like this:
|
44 |
+
````
|
45 |
+
PIPNet
|
46 |
+
-- FaceBoxesV2
|
47 |
+
-- lib
|
48 |
+
-- experiments
|
49 |
+
-- logs
|
50 |
+
-- snapshots
|
51 |
+
-- data
|
52 |
+
|-- data_300W
|
53 |
+
|-- afw
|
54 |
+
|-- helen
|
55 |
+
|-- ibug
|
56 |
+
|-- lfpw
|
57 |
+
|-- COFW
|
58 |
+
|-- COFW_train_color.mat
|
59 |
+
|-- COFW_test_color.mat
|
60 |
+
|-- WFLW
|
61 |
+
|-- WFLW_images
|
62 |
+
|-- WFLW_annotations
|
63 |
+
|-- AFLW
|
64 |
+
|-- flickr
|
65 |
+
|-- AFLWinfo_release.mat
|
66 |
+
|-- LaPa
|
67 |
+
|-- train
|
68 |
+
|-- val
|
69 |
+
|-- test
|
70 |
+
````
|
71 |
+
2. Go to folder `lib`, preprocess a dataset by running ```python preprocess.py DATA_NAME```. For example, to process 300W:
|
72 |
+
```
|
73 |
+
python preprocess.py data_300W
|
74 |
+
```
|
75 |
+
3. Back to folder `PIPNet`, edit `run_train.sh` to choose the config file you want. Then, train the model by running:
|
76 |
+
```
|
77 |
+
sh run_train.sh
|
78 |
+
```
|
79 |
+
|
80 |
+
### Generalizable Semi-supervised Learning
|
81 |
+
Datasets:
|
82 |
+
* data_300W_COFW_WFLW: 300W + COFW-68 (unlabeled) + WFLW-68 (unlabeled)
|
83 |
+
* data_300W_CELEBA: 300W + CelebA (unlabeled)
|
84 |
+
|
85 |
+
1. Download 300W, COFW, and WFLW as in the supervised learning setting. Download annotations of COFW-68 test from [here](https://github.com/golnazghiasi/cofw68-benchmark). For 300W+CelebA, you also need to download the in-the-wild CelebA images from [here](http://mmlab.ie.cuhk.edu.hk/projects/CelebA.html), and the [face bounding boxes](https://drive.google.com/drive/folders/17OwDgJUfuc5_ymQ3QruD8pUnh5zHreP2?usp=sharing) detected by us. The folder structure should look like this:
|
86 |
+
````
|
87 |
+
PIPNet
|
88 |
+
-- FaceBoxesV2
|
89 |
+
-- lib
|
90 |
+
-- experiments
|
91 |
+
-- logs
|
92 |
+
-- snapshots
|
93 |
+
-- data
|
94 |
+
|-- data_300W
|
95 |
+
|-- afw
|
96 |
+
|-- helen
|
97 |
+
|-- ibug
|
98 |
+
|-- lfpw
|
99 |
+
|-- COFW
|
100 |
+
|-- COFW_train_color.mat
|
101 |
+
|-- COFW_test_color.mat
|
102 |
+
|-- WFLW
|
103 |
+
|-- WFLW_images
|
104 |
+
|-- WFLW_annotations
|
105 |
+
|-- data_300W_COFW_WFLW
|
106 |
+
|-- cofw68_test_annotations
|
107 |
+
|-- cofw68_test_bboxes.mat
|
108 |
+
|-- CELEBA
|
109 |
+
|-- img_celeba
|
110 |
+
|-- celeba_bboxes.txt
|
111 |
+
|-- data_300W_CELEBA
|
112 |
+
|-- cofw68_test_annotations
|
113 |
+
|-- cofw68_test_bboxes.mat
|
114 |
+
````
|
115 |
+
2. Go to folder `lib`, preprocess a dataset by running ```python preprocess_gssl.py DATA_NAME```.
|
116 |
+
To process data_300W_COFW_WFLW, run
|
117 |
+
```
|
118 |
+
python preprocess_gssl.py data_300W_COFW_WFLW
|
119 |
+
```
|
120 |
+
To process data_300W_CELEBA, run
|
121 |
+
```
|
122 |
+
python preprocess_gssl.py CELEBA
|
123 |
+
```
|
124 |
+
and
|
125 |
+
```
|
126 |
+
python preprocess_gssl.py data_300W_CELEBA
|
127 |
+
```
|
128 |
+
3. Back to folder `PIPNet`, edit `run_train.sh` to choose the config file you want. Then, train the model by running:
|
129 |
+
```
|
130 |
+
sh run_train.sh
|
131 |
+
```
|
132 |
+
|
133 |
+
## Evaluation
|
134 |
+
1. Edit `run_test.sh` to choose the config file you want. Then, test the model by running:
|
135 |
+
```
|
136 |
+
sh run_test.sh
|
137 |
+
```
|
138 |
+
|
139 |
+
## Community
|
140 |
+
* [lite.ai.toolkit](https://github.com/DefTruth/lite.ai.toolkit): Provide [MNN C++](https://github.com/DefTruth/lite.ai.toolkit/blob/main/lite/mnn/cv/mnn_pipnet98.cpp), [NCNN C++](https://github.com/DefTruth/lite.ai.toolkit/blob/main/lite/ncnn/cv/ncnn_pipnet98.cpp), [TNN C++](https://github.com/DefTruth/lite.ai.toolkit/blob/main/lite/tnn/cv/tnn_pipnet98.cpp) and [ONNXRuntime C++](https://github.com/DefTruth/lite.ai.toolkit/blob/main/lite/ort/cv/pipnet98.cpp) version of PIPNet.
|
141 |
+
* [torchlm](https://github.com/DefTruth/torchlm): Provide a PyTorch re-implement of PIPNet with ONNX Export, can install with pip.
|
142 |
+
|
143 |
+
## Citation
|
144 |
+
````
|
145 |
+
@article{JLS21,
|
146 |
+
title={Pixel-in-Pixel Net: Towards Efficient Facial Landmark Detection in the Wild},
|
147 |
+
author={Haibo Jin and Shengcai Liao and Ling Shao},
|
148 |
+
journal={International Journal of Computer Vision},
|
149 |
+
publisher={Springer Science and Business Media LLC},
|
150 |
+
ISSN={1573-1405},
|
151 |
+
url={http://dx.doi.org/10.1007/s11263-021-01521-4},
|
152 |
+
DOI={10.1007/s11263-021-01521-4},
|
153 |
+
year={2021},
|
154 |
+
month={Sep}
|
155 |
+
}
|
156 |
+
````
|
157 |
+
|
158 |
+
## Acknowledgement
|
159 |
+
We thank the following great works:
|
160 |
+
* [human-pose-estimation.pytorch](https://github.com/microsoft/human-pose-estimation.pytorch)
|
161 |
+
* [HRNet-Facial-Landmark-Detection](https://github.com/HRNet/HRNet-Facial-Landmark-Detection)
|
src/pixel3dmm/preprocessing/PIPNet/data/AFLW/meanface.txt
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
0.2520387312821065 0.22865125462128985 0.3408803567692688 0.20925181543701546 0.4309508960717316 0.2283849860162939 0.5633760922371124 0.22521654882766065 0.6577613879095671 0.20069412873970166 0.7494128254628353 0.21751422299660703 0.29339732989966233 0.3158076280737991 0.35848465881558284 0.31153167254355496 0.4198949142395704 0.3191909005986353 0.5819813735705355 0.3162318018434714 0.6454416413255778 0.3059331736033804 0.7111115695408189 0.3078931922969426 0.403567585150483 0.5334870420541395 0.4963015936690089 0.5077035362328098 0.5978205777158326 0.5306395249630969 0.3843748447832597 0.692393547770251 0.5031717401440071 0.7044968389562082 0.6259229830129976 0.6873232480290753 0.5098649887365728 0.9322687215070251
|
src/pixel3dmm/preprocessing/PIPNet/data/COFW/meanface.txt
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
0.09344842654783869 0.15406877348086334 0.9323471108969382 0.1401049083310136 0.3997603796160685 0.15490567536186625 0.6237975504925628 0.1506668314387944 0.23501464872024747 0.10114569063499716 0.23657257629382072 0.14273999515886135 0.7844072096492979 0.09255827995641538 0.7886209940367209 0.13342958152383141 0.1702434206343547 0.2398254983581864 0.8642419047335136 0.23100885422325879 0.3779708093247684 0.24535590755251818 0.6567150531285483 0.24095057462080818 0.27793516230173154 0.20089460792973152 0.27633082606975745 0.26563845764538907 0.7570995084865105 0.19361548230508704 0.7635889825823677 0.2583984281705357 0.279266369046543 0.2302294117140321 0.7575495684331521 0.22349084426991003 0.38280645505717537 0.4925663990251028 0.6614317708106371 0.488658165265478 0.5189481268032609 0.4708399901570863 0.5225011032592264 0.539587476025657 0.32470035972074895 0.6648848905553355 0.7295419104987368 0.6593261745721221 0.5229449400615745 0.6265737161799486 0.5255912932309097 0.662324568779506 0.527155537232314 0.6983437257351308 0.5293851188286474 0.7515984253648098 0.5353511486450372 0.9458980717418055
|
src/pixel3dmm/preprocessing/PIPNet/data/LaPa/.gitkeep
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
|
src/pixel3dmm/preprocessing/PIPNet/data/LaPa/meanface.txt
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
0.10530529000640856 0.21052138159149678 0.10346312076901258 0.2662726745714962 0.10217057333436477 0.32114553251993 0.10258422967397157 0.3760084841238558 0.10588192925607048 0.43109292350944967 0.11302386489664121 0.48621962292292703 0.12477205483336429 0.5414599600116855 0.14102743093352899 0.5955209925827968 0.1632719376567127 0.6466804471091275 0.1910599572550061 0.6946358073642266 0.22424599203957288 0.7390195138784417 0.26211514659329466 0.7794879334583175 0.30367025470450965 0.816012569068714 0.34766046281821733 0.850882786816955 0.3953177767293077 0.8804344608872823 0.4487173381588481 0.9005324177983531 0.5100338298158771 0.9070606418366286 0.5712716753687324 0.8983023653050762 0.6241767271581117 0.8763255848513388 0.6708553134700462 0.8450314801371582 0.7136791932198043 0.8087428383307392 0.7541248098100394 0.770812423091051 0.7905250092801029 0.7290677819826883 0.8219967896955132 0.6833908711520263 0.8479404285884548 0.6343345325292671 0.8681874714540011 0.5821458724936195 0.8824175512748297 0.5274128341115184 0.8920174566936556 0.471437455135775 0.8971160168752679 0.4160147078312381 0.8984258108227322 0.36087818978988345 0.8967746520532384 0.30593953132086726 0.8932401684842185 0.2510184159487108 0.8886303936473524 0.19551555989951783 0.19080691089284976 0.17688226731422843 0.23703774601603758 0.13493690623969778 0.2994011235863562 0.12377371262269846 0.36442443812566794 0.1334156515414588 0.4206974462185849 0.15576893350782198 0.41538261991372216 0.18521387259748126 0.3578316077351047 0.17023713987254602 0.29926531681027724 0.1647584864314877 0.24376522496647846 0.16810390551348878 0.5679133390211937 0.15195666209513556 0.6234099235893878 0.1271788852505303 0.68836638284106 0.11502664609938558 0.7517148773395326 0.12397312576453914 0.8003186915478934 0.164661447404218 0.7461363917064738 0.1568570738057735 0.6902508869620426 0.15554025558991308 0.6316039289402061 0.16367758210908348 0.5745440209110346 0.1811702067173649 0.49635250721509805 0.23144344163945024 0.49776198821318396 0.30385803807833195 0.4991020889198753 0.3763030566695691 0.5004707578148508 0.44878030556582904 0.4382571815965156 0.26036872039531744 0.4131953004760858 0.40603519461106263 0.3881451065329989 0.471487759479652 0.4214523196091174 0.4971740638884675 0.4594663412069896 0.5065521839440414 0.5024819453368541 0.5179592883408858 0.5451122880635956 0.5043415278881611 0.5824119573939653 0.49388732408483804 0.6146171697397168 0.4665300926927993 0.5867368809383912 0.4020947987203815 0.5559811904454144 0.2576938678584477 0.2531314405041606 0.252719744146067 0.2853408047822641 0.23135591608026138 0.3258440646145571 0.2229636137476243 0.36658273457129226 0.23242953378754497 0.39829919754027615 0.25834900060080085 0.3626412317888289 0.2666381129849394 0.3234940413093194 0.2711006990366015 0.28546434003392307 0.2657038110483953 0.3259425084155361 0.24452859898165027 0.5962922590838732 0.25440679232096053 0.6270469522613061 0.22729509647219456 0.6674316022765016 0.21638754266341426 0.7081748622553374 0.2234007704800147 0.7408849029025555 0.2436734338635688 0.7093069690599688 0.25797173644014293 0.6715889798302642 0.2648049864304249 0.6322345940201518 0.2615942138918854 0.6686493178688638 0.2381846027535789 0.35073794231894434 0.6264851851541189 0.40579598288417945 0.6042815280826724 0.4679809697527211 0.5906101560830487 0.5025555655287725 0.5975087613065031 0.5368258366138642 0.5893932526555288 0.5996684030376771 0.600799080968945 0.6565447626583086 0.62072352127923 0.6189097233474866 0.6655963252276111 0.5709337146008885 0.698894831978254 0.5048366317585606 0.713019897126309 0.4380289691984558 0.7014141971577583 0.38932170182206044 0.66978410405136 0.3739501137612586 0.6290623209341267 0.4264911280653227 0.6243811766819207 0.5031035985986991 0.6271183438753134 0.579761780602956 0.6215714757222834 0.6332962211716711 0.6243463702139462 0.5831229602285424 0.648154374088437 0.5038091891864612 0.6612169580713776 0.42442126476527914 0.6512543499529478 0.32595499952970813 0.2445329023949036 0.6686401132878527 0.2381823527614187
|
src/pixel3dmm/preprocessing/PIPNet/data/WFLW/meanface.txt
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
0.07960419395480703 0.3921576875344978 0.08315055593117261 0.43509551571809146 0.08675705281580391 0.47810288286566444 0.09141892980469117 0.5210356946467262 0.09839925903528965 0.5637522280060038 0.10871037524559955 0.6060410614977951 0.12314562992759207 0.6475338700558225 0.14242389255404694 0.6877152027028081 0.16706295456951875 0.7259564546408682 0.19693946055282413 0.761730578566735 0.23131827931527224 0.7948205670466106 0.2691730934906831 0.825332081636482 0.3099415030959131 0.853325959406618 0.3535202097901413 0.8782538906229107 0.40089023799272033 0.8984102434399625 0.4529251732310723 0.9112191359814178 0.5078640056794708 0.9146712690731943 0.5616519666079889 0.9094327772020283 0.6119216923689698 0.8950540037623425 0.6574617882337107 0.8738084866764846 0.6994820494908942 0.8482660530943744 0.7388135339780575 0.8198750461527688 0.775158750479601 0.788989141243473 0.8078785221990765 0.7555462713420953 0.8361052138935441 0.7195542055115057 0.8592123871172533 0.6812759034843933 0.8771159986952748 0.6412243940605555 0.8902481006481506 0.5999743595282084 0.8992952868651163 0.5580032282594118 0.9050110573289222 0.5156548913779377 0.908338439928252 0.4731336721500472 0.9104896075281127 0.4305382486815422 0.9124796341441906 0.38798192678294363 0.18465941635742913 0.35063191749632183 0.24110421889338157 0.31190394310826886 0.3003235400132397 0.30828189837331976 0.3603094923651325 0.3135606490643205 0.4171060234289877 0.32433417646045615 0.416842139562573 0.3526729965541497 0.36011177591813404 0.3439660526998693 0.3000863121140166 0.33890077494044946 0.24116055928407834 0.34065620413845005 0.5709736930161899 0.321407825750195 0.6305694459247149 0.30972642336729495 0.6895161625920927 0.3036453838462943 0.7488591859761683 0.3069143844433495 0.8030471337135181 0.3435156012309415 0.7485083446528741 0.3348759588212388 0.6893025057931884 0.33403402013776456 0.6304822892126991 0.34038458762875695 0.5710009285609654 0.34988479902594455 0.4954171902473609 0.40202330022004634 0.49604903449415433 0.4592869389138444 0.49644391662771625 0.5162862508677217 0.4981161256057368 0.5703284628419502 0.40749001573145566 0.5983629921847019 0.4537396729649631 0.6057169923583451 0.5007345777827058 0.6116695615531077 0.5448481727980428 0.6044131443745976 0.5882140504891681 0.5961738788380111 0.24303324896316683 0.40721003719912746 0.27771706732644313 0.3907171413930685 0.31847706697401107 0.38417234007271117 0.3621792860449715 0.3900847721320633 0.3965299162804086 0.41071434661355205 0.3586805562211872 0.4203724421417311 0.31847860588240934 0.4237674602252073 0.2789458001651631 0.41942757306509065 0.5938514626567266 0.4090628827047304 0.6303565516542536 0.3864501652756091 0.6774844732813035 0.3809319896905685 0.7150854850525555 0.3875173254527522 0.747519807465081 0.4025187328459307 0.7155172856447009 0.4145958479293519 0.680051949453018 0.420041513473271 0.6359056750107122 0.41803782782566573 0.33916483987223056 0.6968581311227738 0.40008790639758807 0.6758101185779204 0.47181947887764153 0.6678850445191217 0.5025394453374782 0.6682917934792593 0.5337748367911458 0.6671949030019636 0.6015915330083903 0.6742535357237751 0.6587068892667173 0.6932163943648724 0.6192795131720007 0.7283129162844936 0.5665923267827963 0.7550248076404299 0.5031303335863617 0.7648348885181623 0.4371030429958871 0.7572539606688756 0.3814909500115824 0.7320595346122074 0.35129809553480984 0.6986839074746692 0.4247987356100664 0.69127609583798 0.5027677238758598 0.6911145821740593 0.576997542122097 0.6896269708051024 0.6471352843446794 0.6948977432227927 0.5799932528781817 0.7185288017567538 0.5024914756021335 0.7285408331555782 0.4218115644247556 0.7209126133193829 0.3219750495122499 0.40376441481225156 0.6751136343101699 0.40023415216110797
|
src/pixel3dmm/preprocessing/PIPNet/data/data_300W/meanface.txt
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
0.05558998895410058 0.23848280098218655 0.05894856684324656 0.3590187767402909 0.0736574254414371 0.4792196439871159 0.09980016420365162 0.5959029676167197 0.14678670154995865 0.7035615597409001 0.21847188218752928 0.7971705893013413 0.30554692814599393 0.8750572978073209 0.4018434142644611 0.9365018059444535 0.5100536090382116 0.9521295666029498 0.6162039414413925 0.9309467340899419 0.7094522484942942 0.8669275031738761 0.7940993502957612 0.7879369615524398 0.8627063649669019 0.6933756633633967 0.9072386130534111 0.5836975017700834 0.9298874997796132 0.4657004930314701 0.9405202670724796 0.346063993805527 0.9425419553088846 0.22558131891345742 0.13304298285530403 0.14853071838028062 0.18873587368440375 0.09596491613770254 0.2673231915839219 0.08084218279128136 0.34878638553224905 0.09253591849498964 0.4226713753717798 0.12466063383809506 0.5618513152452376 0.11839668911898667 0.6394952560845826 0.08480191391770678 0.7204375851516752 0.07249669092117161 0.7988615904537885 0.08766933146893043 0.8534884939460948 0.1380096813348583 0.49610677423740546 0.21516740699375395 0.49709661403980665 0.2928875699060973 0.4982292618461611 0.3699985379939941 0.49982965173254235 0.4494119144493957 0.406772397599095 0.5032397294041786 0.45231994786363067 0.5197953144002292 0.49969685987914064 0.5332489262413073 0.5470074224053442 0.518413595827126 0.5892261151542287 0.5023530079850803 0.22414578747180394 0.22835847349949062 0.27262947128194215 0.19915251892241678 0.3306759252861797 0.20026034220607236 0.38044435864341913 0.23839196034290633 0.32884072789429913 0.24902443794896897 0.2707409300714473 0.24950886025380967 0.6086826011068529 0.23465048639345917 0.660397116846103 0.1937087938594717 0.7177815187666494 0.19317079039835858 0.7652328176062365 0.22088822845258235 0.722727677909097 0.24195514178450958 0.6658378927310327 0.2441554205021945 0.32894370935769124 0.6496589505331646 0.39347179739100613 0.6216899667490776 0.4571976492475472 0.60794251109236 0.4990484623797022 0.6190124015360254 0.5465555522325872 0.6071477960565326 0.6116127327356168 0.6205387097430033 0.6742318496058836 0.6437466364395467 0.6144773141699744 0.7077526646009754 0.5526442055374252 0.7363350735898412 0.5018120662554302 0.7424476622366345 0.4554458875556401 0.7382303858617719 0.3923750731597415 0.7118887028663435 0.35530766372404593 0.6524479416354049 0.457111071610868 0.6467108367268608 0.49974082228815025 0.6508406774477011 0.5477027224368399 0.6451242819422733 0.6478392760505715 0.647852382880368 0.5488474760115958 0.6779061893042735 0.5001073351044452 0.6845280260362221 0.4564831746654594 0.6799300301441035
|
src/pixel3dmm/preprocessing/PIPNet/data/data_300W_CELEBA/meanface.txt
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
0.12232440867025321 0.27962262481578615 0.1251741407890332 0.3822010530676433 0.137662109340586 0.484494826453967 0.15985504610693665 0.58379829864377 0.19972896480368596 0.675412639432648 0.2605579295545752 0.7550617213398176 0.33444765501965257 0.8213252459974902 0.4161697591327947 0.8735651108778814 0.5080087528764403 0.8868348215817158 0.5980992802776127 0.8688135857462302 0.6772596499687593 0.8143677086997837 0.7491211575789162 0.7471655230329272 0.8073766483264004 0.6667089668374325 0.8451875673796937 0.5733850777608563 0.864415472750196 0.4729803701239298 0.8734385478428245 0.3711768994830678 0.8751531101099292 0.268656781257751 0.18796548820344416 0.2030530402265248 0.23523864911193537 0.15830034643403879 0.3019430356817159 0.14541898323850677 0.37108573686879104 0.15536530774545093 0.4337977392176639 0.18270698888639544 0.5519376178836386 0.17738031243713215 0.6178610694743013 0.14878977678287292 0.6865865025820168 0.13831990409096662 0.7531734388993169 0.1512429054491697 0.7995673014066828 0.1941022399185316 0.49613115054318335 0.2597672071212774 0.4969637683612954 0.3259085874268994 0.49791780500402 0.39152877663527796 0.49926918905146594 0.4591065683857296 0.4202846654961633 0.5049368052770046 0.4589485206700924 0.5190228657842618 0.49916996608981484 0.5304667753993072 0.5393424804128895 0.5178452264471334 0.575195669558906 0.5041819599878575 0.26527901675348586 0.27098957028846976 0.3064399715133211 0.24611940114541314 0.3557195490030035 0.24706273924128783 0.39798274421817326 0.2795361944817882 0.35416233167951755 0.28858943241231877 0.3048346296119043 0.28900292977320297 0.5917141352695678 0.2763518687602816 0.6356260268180847 0.2414897723496627 0.6843481684971716 0.24103035776326823 0.7246470986193275 0.26462826587645844 0.6885499499583031 0.2825693401736116 0.6402432833345117 0.2844445142656967 0.3542788870635578 0.6295669131323691 0.4090264228452472 0.6057706295562828 0.4631091980648265 0.5940616118908922 0.49863392623478087 0.6034872665752211 0.5389612978421857 0.5933843819273095 0.5941962379203847 0.6047869787643673 0.6473762083732608 0.6245291762913125 0.5966343734828656 0.67897568285239 0.5441373367855241 0.7033053722799186 0.500984722244293 0.708509427837014 0.4616264195190659 0.7049230677252907 0.4080980619951271 0.6825102595145595 0.3766575821628222 0.6319366801368325 0.46303659510988915 0.6270534512838973 0.4992240769447232 0.6305695809640286 0.5399375315807448 0.6257030961252895 0.6249688623037122 0.6280212667827051 0.5409104430529676 0.6535813164521486 0.49953581963561644 0.6592166737899897 0.4625043556133079 0.6553049004525271
|
src/pixel3dmm/preprocessing/PIPNet/data/data_300W_COFW_WFLW/meanface.txt
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
0.12232440867025321 0.27962262481578615 0.1251741407890332 0.3822010530676433 0.137662109340586 0.484494826453967 0.15985504610693665 0.58379829864377 0.19972896480368596 0.675412639432648 0.2605579295545752 0.7550617213398176 0.33444765501965257 0.8213252459974902 0.4161697591327947 0.8735651108778814 0.5080087528764403 0.8868348215817158 0.5980992802776127 0.8688135857462302 0.6772596499687593 0.8143677086997837 0.7491211575789162 0.7471655230329272 0.8073766483264004 0.6667089668374325 0.8451875673796937 0.5733850777608563 0.864415472750196 0.4729803701239298 0.8734385478428245 0.3711768994830678 0.8751531101099292 0.268656781257751 0.18796548820344416 0.2030530402265248 0.23523864911193537 0.15830034643403879 0.3019430356817159 0.14541898323850677 0.37108573686879104 0.15536530774545093 0.4337977392176639 0.18270698888639544 0.5519376178836386 0.17738031243713215 0.6178610694743013 0.14878977678287292 0.6865865025820168 0.13831990409096662 0.7531734388993169 0.1512429054491697 0.7995673014066828 0.1941022399185316 0.49613115054318335 0.2597672071212774 0.4969637683612954 0.3259085874268994 0.49791780500402 0.39152877663527796 0.49926918905146594 0.4591065683857296 0.4202846654961633 0.5049368052770046 0.4589485206700924 0.5190228657842618 0.49916996608981484 0.5304667753993072 0.5393424804128895 0.5178452264471334 0.575195669558906 0.5041819599878575 0.26527901675348586 0.27098957028846976 0.3064399715133211 0.24611940114541314 0.3557195490030035 0.24706273924128783 0.39798274421817326 0.2795361944817882 0.35416233167951755 0.28858943241231877 0.3048346296119043 0.28900292977320297 0.5917141352695678 0.2763518687602816 0.6356260268180847 0.2414897723496627 0.6843481684971716 0.24103035776326823 0.7246470986193275 0.26462826587645844 0.6885499499583031 0.2825693401736116 0.6402432833345117 0.2844445142656967 0.3542788870635578 0.6295669131323691 0.4090264228452472 0.6057706295562828 0.4631091980648265 0.5940616118908922 0.49863392623478087 0.6034872665752211 0.5389612978421857 0.5933843819273095 0.5941962379203847 0.6047869787643673 0.6473762083732608 0.6245291762913125 0.5966343734828656 0.67897568285239 0.5441373367855241 0.7033053722799186 0.500984722244293 0.708509427837014 0.4616264195190659 0.7049230677252907 0.4080980619951271 0.6825102595145595 0.3766575821628222 0.6319366801368325 0.46303659510988915 0.6270534512838973 0.4992240769447232 0.6305695809640286 0.5399375315807448 0.6257030961252895 0.6249688623037122 0.6280212667827051 0.5409104430529676 0.6535813164521486 0.49953581963561644 0.6592166737899897 0.4625043556133079 0.6553049004525271
|
src/pixel3dmm/preprocessing/PIPNet/experiments/AFLW/__pycache__/pip_32_16_60_r101_l2_l1_10_1_nb10.cpython-37.pyc
ADDED
Binary file (850 Bytes). View file
|
|
src/pixel3dmm/preprocessing/PIPNet/experiments/AFLW/__pycache__/pip_32_16_60_r152_l2_l1_10_1_nb10.cpython-37.pyc
ADDED
Binary file (899 Bytes). View file
|
|
src/pixel3dmm/preprocessing/PIPNet/experiments/AFLW/__pycache__/pip_32_16_60_r18_focal_l1_01_1.cpython-37.pyc
ADDED
Binary file (918 Bytes). View file
|
|
src/pixel3dmm/preprocessing/PIPNet/experiments/AFLW/__pycache__/pip_32_16_60_r18_focal_l2_01_1.cpython-37.pyc
ADDED
Binary file (918 Bytes). View file
|
|
src/pixel3dmm/preprocessing/PIPNet/experiments/AFLW/__pycache__/pip_32_16_60_r18_l2_l1_10_1.cpython-37.pyc
ADDED
Binary file (905 Bytes). View file
|
|
src/pixel3dmm/preprocessing/PIPNet/experiments/AFLW/__pycache__/pip_32_16_60_r18_l2_l1_10_1_nb10.cpython-37.pyc
ADDED
Binary file (848 Bytes). View file
|
|
src/pixel3dmm/preprocessing/PIPNet/experiments/AFLW/__pycache__/pip_32_16_60_r18_l2_l1_10_1_nb2.cpython-37.pyc
ADDED
Binary file (929 Bytes). View file
|
|
src/pixel3dmm/preprocessing/PIPNet/experiments/AFLW/__pycache__/pip_32_16_60_r18_l2_l1_10_1_nb5.cpython-37.pyc
ADDED
Binary file (934 Bytes). View file
|
|
src/pixel3dmm/preprocessing/PIPNet/experiments/AFLW/__pycache__/pip_32_16_60_r18_l2_l2_10_1.cpython-37.pyc
ADDED
Binary file (901 Bytes). View file
|
|
src/pixel3dmm/preprocessing/PIPNet/experiments/AFLW/__pycache__/pip_32_16_60_r50_l2_l1_10_1.cpython-37.pyc
ADDED
Binary file (905 Bytes). View file
|
|
src/pixel3dmm/preprocessing/PIPNet/experiments/AFLW/__pycache__/pip_32_16_60_r50_l2_l1_10_1_nb10.cpython-37.pyc
ADDED
Binary file (892 Bytes). View file
|
|
src/pixel3dmm/preprocessing/PIPNet/experiments/AFLW/__pycache__/pip_32_16_60_r50_l2_l1_10_1_nb2.cpython-37.pyc
ADDED
Binary file (929 Bytes). View file
|
|
src/pixel3dmm/preprocessing/PIPNet/experiments/AFLW/__pycache__/pip_32_16_60_r50_l2_l1_10_1_nb5.cpython-37.pyc
ADDED
Binary file (934 Bytes). View file
|
|
src/pixel3dmm/preprocessing/PIPNet/experiments/AFLW/pip_32_16_60_r101_l2_l1_10_1_nb10.py
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
class Config():
|
3 |
+
def __init__(self):
|
4 |
+
self.det_head = 'pip'
|
5 |
+
self.net_stride = 32
|
6 |
+
self.batch_size = 16
|
7 |
+
self.init_lr = 0.0001
|
8 |
+
self.num_epochs = 60
|
9 |
+
self.decay_steps = [30, 50]
|
10 |
+
self.input_size = 256
|
11 |
+
self.backbone = 'resnet101'
|
12 |
+
self.pretrained = True
|
13 |
+
self.criterion_cls = 'l2'
|
14 |
+
self.criterion_reg = 'l1'
|
15 |
+
self.cls_loss_weight = 10
|
16 |
+
self.reg_loss_weight = 1
|
17 |
+
self.num_lms = 19
|
18 |
+
self.save_interval = self.num_epochs
|
19 |
+
self.num_nb = 10
|
20 |
+
self.use_gpu = True
|
21 |
+
self.gpu_id = 4
|
src/pixel3dmm/preprocessing/PIPNet/experiments/AFLW/pip_32_16_60_r18_l2_l1_10_1_nb10.py
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
class Config():
|
3 |
+
def __init__(self):
|
4 |
+
self.det_head = 'pip'
|
5 |
+
self.net_stride = 32
|
6 |
+
self.batch_size = 16
|
7 |
+
self.init_lr = 0.0001
|
8 |
+
self.num_epochs = 60
|
9 |
+
self.decay_steps = [30, 50]
|
10 |
+
self.input_size = 256
|
11 |
+
self.backbone = 'resnet18'
|
12 |
+
self.pretrained = True
|
13 |
+
self.criterion_cls = 'l2'
|
14 |
+
self.criterion_reg = 'l1'
|
15 |
+
self.cls_loss_weight = 10
|
16 |
+
self.reg_loss_weight = 1
|
17 |
+
self.num_lms = 19
|
18 |
+
self.save_interval = self.num_epochs
|
19 |
+
self.num_nb = 10
|
20 |
+
self.use_gpu = True
|
21 |
+
self.gpu_id = 3
|
src/pixel3dmm/preprocessing/PIPNet/experiments/AFLW/pip_32_16_60_r50_l2_l1_10_1_nb10.py
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
class Config():
|
3 |
+
def __init__(self):
|
4 |
+
self.det_head = 'pip'
|
5 |
+
self.net_stride = 32
|
6 |
+
self.batch_size = 16
|
7 |
+
self.init_lr = 0.0001
|
8 |
+
self.num_epochs = 60
|
9 |
+
self.decay_steps = [30, 50]
|
10 |
+
self.input_size = 256
|
11 |
+
self.backbone = 'resnet50'
|
12 |
+
self.pretrained = True
|
13 |
+
self.criterion_cls = 'l2'
|
14 |
+
self.criterion_reg = 'l1'
|
15 |
+
self.cls_loss_weight = 10
|
16 |
+
self.reg_loss_weight = 1
|
17 |
+
self.num_lms = 19
|
18 |
+
self.save_interval = self.num_epochs
|
19 |
+
self.num_nb = 10
|
20 |
+
self.use_gpu = True
|
21 |
+
self.gpu_id = 2
|
src/pixel3dmm/preprocessing/PIPNet/experiments/COFW/__pycache__/pip_32_16_60_r101_l2_l1_10_1_nb10.cpython-37.pyc
ADDED
Binary file (850 Bytes). View file
|
|
src/pixel3dmm/preprocessing/PIPNet/experiments/COFW/__pycache__/pip_32_16_60_r152_l2_l1_10_1_nb10.cpython-37.pyc
ADDED
Binary file (899 Bytes). View file
|
|