-
Notifications
You must be signed in to change notification settings - Fork 143
/
face_detection.py
140 lines (109 loc) · 5.83 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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
import cv2
import numpy as np
import dlib
from imutils import face_utils
import imutils
class FaceDetection(object):
def __init__(self):
self.detector = dlib.get_frontal_face_detector()
self.predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
self.fa = face_utils.FaceAligner(self.predictor, desiredFaceWidth=256)
def face_detect(self, frame):
#frame = imutils.resize(frame, width=400)
face_frame = np.zeros((10, 10, 3), np.uint8)
mask = np.zeros((10, 10, 3), np.uint8)
ROI1 = np.zeros((10, 10, 3), np.uint8)
ROI2 = np.zeros((10, 10, 3), np.uint8)
#ROI3 = np.zeros((10, 10, 3), np.uint8)
status = False
if frame is None:
return
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# detect faces in the grayscale image
rects = self.detector(gray, 0)
# loop over the face detections
#for (i, rect) in enumerate(rects):
# determine the facial landmarks for the face region, then
# convert the facial landmark (x, y)-coordinates to a NumPy
# array
#assumpion: only 1 face is detected
if len(rects)>0:
status = True
# shape = self.predictor(gray, rects[0])
# shape = face_utils.shape_to_np(shape)
# convert dlib's rectangle to a OpenCV-style bounding box
# [i.e., (x, y, w, h)], then draw the face bounding box
(x, y, w, h) = face_utils.rect_to_bb(rects[0])
#cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 1)
if y<0:
print("a")
return frame, face_frame, ROI1, ROI2, status, mask
#if i==0:
face_frame = frame[y:y+h,x:x+w]
# show the face number
#cv2.putText(frame, "Face #{}".format(i + 1), (x - 10, y - 10),
# cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)
# loop over the (x, y)-coordinates for the facial landmarks
# and draw them on the image
# for (x, y) in shape:
# cv2.circle(frame, (x, y), 1, (0, 0, 255), -1) #draw facial landmarks
if(face_frame.shape[:2][1] != 0):
face_frame = imutils.resize(face_frame,width=256)
# face_frame = self.fa.align(frame,gray,rects[0]) # align face
grayf = cv2.cvtColor(face_frame, cv2.COLOR_BGR2GRAY)
rectsf = self.detector(grayf, 0)
if len(rectsf) >0:
shape = self.predictor(grayf, rectsf[0])
shape = face_utils.shape_to_np(shape)
for (a, b) in shape:
cv2.circle(face_frame, (a, b), 1, (0, 0, 255), -1) #draw facial landmarks
cv2.rectangle(face_frame,(shape[54][0], shape[29][1]), #draw rectangle on right and left cheeks
(shape[12][0],shape[33][1]), (0,255,0), 0)
cv2.rectangle(face_frame, (shape[4][0], shape[29][1]),
(shape[48][0],shape[33][1]), (0,255,0), 0)
ROI1 = face_frame[shape[29][1]:shape[33][1], #right cheek
shape[54][0]:shape[12][0]]
ROI2 = face_frame[shape[29][1]:shape[33][1], #left cheek
shape[4][0]:shape[48][0]]
# ROI3 = face_frame[shape[29][1]:shape[33][1], #nose
# shape[31][0]:shape[35][0]]
#get the shape of face for color amplification
rshape = np.zeros_like(shape)
rshape = self.face_remap(shape)
mask = np.zeros((face_frame.shape[0], face_frame.shape[1]))
cv2.fillConvexPoly(mask, rshape[0:27], 1)
# mask = np.zeros((face_frame.shape[0], face_frame.shape[1],3),np.uint8)
# cv2.fillConvexPoly(mask, shape, 1)
#cv2.imshow("face align", face_frame)
# cv2.rectangle(frame,(shape[54][0], shape[29][1]), #draw rectangle on right and left cheeks
# (shape[12][0],shape[54][1]), (0,255,0), 0)
# cv2.rectangle(frame, (shape[4][0], shape[29][1]),
# (shape[48][0],shape[48][1]), (0,255,0), 0)
# ROI1 = frame[shape[29][1]:shape[54][1], #right cheek
# shape[54][0]:shape[12][0]]
# ROI2 = frame[shape[29][1]:shape[54][1], #left cheek
# shape[4][0]:shape[48][0]]
else:
cv2.putText(frame, "No face detected",
(200,200), cv2.FONT_HERSHEY_PLAIN, 1.5, (0, 0, 255),2)
status = False
return frame, face_frame, ROI1, ROI2, status, mask
# some points in the facial landmarks need to be re-ordered
def face_remap(self,shape):
remapped_image = shape.copy()
# left eye brow
remapped_image[17] = shape[26]
remapped_image[18] = shape[25]
remapped_image[19] = shape[24]
remapped_image[20] = shape[23]
remapped_image[21] = shape[22]
# right eye brow
remapped_image[22] = shape[21]
remapped_image[23] = shape[20]
remapped_image[24] = shape[19]
remapped_image[25] = shape[18]
remapped_image[26] = shape[17]
# neatening
remapped_image[27] = shape[0]
remapped_image = cv2.convexHull(shape)
return remapped_image