1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
|
import os
from os.path import join
from pathlib import Path
import cv2 as cv
import numpy as np
import imutils
from app.utils import im_utils, logger_utils
from app.models.bbox import BBox
from app.settings import app_cfg as cfg
from app.settings import types
from app.models.bbox import BBox
class LandmarksFaceAlignment:
# Estimates 2D facial landmarks
import face_alignment
def __init__(self, gpu=0):
self.log = logger_utils.Logger.getLogger()
device = f'cuda:{gpu}' if gpu > -1 else 'cpu'
self.fa = face_alignment.FaceAlignment(face_alignment.LandmarksType._2D, device=device, flip_input=True)
def landmarks(self, im, as_type=str):
'''Calculates the 3D facial landmarks
:param im: (numpy.ndarray) image
:param as_type: (str) or (list) type to return data
'''
preds = self.fa.get_landmarks(im)
# convert to comma separated ints
# storing data as "[1,2], [3,4]" is larger file size than storing as "1,2,3,4"
# storing a list object in Pandas seems to result in 30% larger CSV files
# TODO optimize this
preds_int = [list(map(int, x)) for x in preds[0]] # list of ints
if as_type is str:
return ','.join([','.join(list(map(str,[x,y]))) for x,y in preds_int])
else:
return preds_int
class LandmarksDLIB:
def __init__(self):
# init dlib
import dlib
self.log = logger_utils.Logger.getLogger()
self.predictor = dlib.shape_predictor(cfg.DIR_MODELS_DLIB_68PT)
def landmarks(self, im, bbox):
# Draw high-confidence faces
dim = im.shape[:2][::-1]
bbox = bbox.to_dlib()
im_gray = cv.cvtColor(im, cv.COLOR_BGR2GRAY)
landmarks = [[p.x, p.y] for p in self.predictor(im_gray, bbox).parts()]
return landmarks
class LandmarksMTCNN:
# https://github.com/ipazc/mtcnn
# pip install mtcnn
dnn_size = (400, 400)
def __init__(self, size=(400,400)):
from mtcnn.mtcnn import MTCNN
self.detector = MTCNN()
def landmarks(self, im, opt_size=None, opt_conf_thresh=None, opt_pyramids=None):
'''Detects face using MTCNN and returns (list) of BBox
:param im: (numpy.ndarray) image
:returns list of BBox
'''
rois = []
dnn_size = self.dnn_size if opt_size is None else opt_size
im = im_utils.resize(im, width=dnn_size[0], height=dnn_size[1])
dim = im.shape[:2][::-1]
# run MTCNN
dets = self.detector.detect_faces(im)
for det in dets:
rect = det['box']
keypoints = det['keypoints'] # not using here. see 'face_landmarks.py'
bbox = BBox.from_xywh_dim(*rect, dim)
rois.append(bbox)
return rois
|