forked from wuhuikai/FaceSwap
-
Notifications
You must be signed in to change notification settings - Fork 0
/
face_detection.py
95 lines (73 loc) · 3.06 KB
/
face_detection.py
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
88
89
90
91
92
93
94
95
import cv2
import dlib
import numpy as np
## Face detection
def face_detection(img,upsample_times=1):
# Ask the detector to find the bounding boxes of each face. The 1 in the
# second argument indicates that we should upsample the image 1 time. This
# will make everything bigger and allow us to detect more faces.
detector = dlib.get_frontal_face_detector()
faces = detector(img, upsample_times)
return faces
PREDICTOR_PATH = 'models/shape_predictor_68_face_landmarks.dat'
predictor = dlib.shape_predictor(PREDICTOR_PATH)
## Face and points detection
def face_points_detection(img, bbox:dlib.rectangle):
# Get the landmarks/parts for the face in box d.
shape = predictor(img, bbox)
# loop over the 68 facial landmarks and convert them
# to a 2-tuple of (x, y)-coordinates
coords = np.asarray(list([p.x, p.y] for p in shape.parts()), dtype=np.int)
# return the array of (x, y)-coordinates
return coords
def select_face(im, r=10, choose=True):
faces = face_detection(im)
if len(faces) == 0:
return None, None, None
if len(faces) == 1 or not choose:
idx = np.argmax([(face.right() - face.left()) * (face.bottom() - face.top()) for face in faces])
bbox = faces[idx]
else:
bbox = []
def click_on_face(event, x, y, flags, params):
if event != cv2.EVENT_LBUTTONDOWN:
return
for face in faces:
if face.left() < x < face.right() and face.top() < y < face.bottom():
bbox.append(face)
break
im_copy = im.copy()
for face in faces:
# draw the face bounding box
cv2.rectangle(im_copy, (face.left(), face.top()), (face.right(), face.bottom()), (0, 0, 255), 1)
cv2.imshow('Click the Face:', im_copy)
cv2.setMouseCallback('Click the Face:', click_on_face)
while len(bbox) == 0:
cv2.waitKey(1)
cv2.destroyAllWindows()
bbox = bbox[0]
points = np.asarray(face_points_detection(im, bbox))
im_w, im_h = im.shape[:2]
left, top = np.min(points, 0)
right, bottom = np.max(points, 0)
x, y = max(0, left - r), max(0, top - r)
w, h = min(right + r, im_h) - x, min(bottom + r, im_w) - y
return points - np.asarray([[x, y]]), (x, y, w, h), im[y:y + h, x:x + w]
def select_all_faces(im, r=10):
faces = face_detection(im)
if len(faces) == 0:
return None
faceBoxes = {k : {"points" : None,
"shape" : None,
"face" : None} for k in range(len(faces))}
for i, bbox in enumerate(faces):
points = np.asarray(face_points_detection(im, bbox))
im_w, im_h = im.shape[:2]
left, top = np.min(points, 0)
right, bottom = np.max(points, 0)
x, y = max(0, left - r), max(0, top - r)
w, h = min(right + r, im_h) - x, min(bottom + r, im_w) - y
faceBoxes[i]["points"] = points - np.asarray([[x, y]])
faceBoxes[i]["shape"] = (x, y, w, h)
faceBoxes[i]["face"] = im[y:y + h, x:x + w]
return faceBoxes