-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathfaceDetector.py
executable file
·127 lines (94 loc) · 4 KB
/
faceDetector.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
import cv2
from keras.preprocessing import image
import numpy as np
import math
def findEuclideanDistance(source_representation, test_representation):
if type(source_representation) == list:
source_representation = np.array(source_representation)
if type(test_representation) == list:
test_representation = np.array(test_representation)
euclidean_distance = source_representation - test_representation
euclidean_distance = np.sum(np.multiply(euclidean_distance, euclidean_distance))
euclidean_distance = np.sqrt(euclidean_distance)
return euclidean_distance
def process_face(img, target_size=(48,48), to_gray=True):
"""
Modifie la taille de la matrice en target_size
"""
if to_gray:
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img = cv2.resize(img, target_size)
if to_gray:
img = np.expand_dims(img, axis = 0)
img = np.divide(img, 255)
return img
def align_face(img):
eye_detector = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_eye.xml')
detected_face_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) #eye detector expects gray scale image
eyes = eye_detector.detectMultiScale(detected_face_gray, 1.1, 10)
# Si le classifier a détecté une seul (ou zéro) oeil on retourne None
# Sinon on éssaye de detecter l'orientation
if len(eyes) >= 2:
eye_1 = eyes[0]; eye_2 = eyes[1]
# detect quel oeil est le gauche et lequel est le droit sur base
# de la position x (x plus petit = gauche)
if eye_1[0] < eye_2[0]:
left_eye = eye_1; right_eye = eye_2
else:
left_eye = eye_2; right_eye = eye_1
#-----------------------
#find center of eyes
# (x + x+w)/2 = centre x (y+y+h)/2 = centre y
left_eye = (int(left_eye[0] + (left_eye[2] / 2)), int(left_eye[1] + (left_eye[3] / 2)))
right_eye = (int(right_eye[0] + (right_eye[2]/2)), int(right_eye[1] + (right_eye[3]/2)))
#-----------------------
#find rotation direction
left_eye_x, left_eye_y = left_eye
right_eye_x, right_eye_y = right_eye
if left_eye_y > right_eye_y:
point_3rd = (right_eye_x, left_eye_y)
# anti trigonométrique
direction = -1 #rotate same direction to clock
else:
point_3rd = (left_eye_x, right_eye_y)
# trigonométrique
direction = 1 #rotate inverse direction of clock
#-----------------------
#find length of triangle edges
a = findEuclideanDistance(np.array(left_eye), np.array(point_3rd))
b = findEuclideanDistance(np.array(right_eye), np.array(point_3rd))
c = findEuclideanDistance(np.array(right_eye), np.array(left_eye))
#-----------------------
#apply cosine rule
# Si b ou c = 0 ça veut dire que les yeux sont alignés (tête droite)
if b != 0 and c != 0:
cos_a = (b*b + c*c - a*a)/(2*b*c)
angle = np.arccos(cos_a) #angle in radian
angle = (angle * 180) / math.pi #radian to degree
if direction == -1:
angle = 90 - angle
return direction * angle
return None
return None
def detect_faces(img, face_detector):
"""
Detect and isolate the head in the img
"""
resp = []
faces = []
try:
# Tableau qui contient un tableau de 4 points formant un rectangle autour de la tete
# [[0, 12, 12, 23]]
faces = face_detector.detectMultiScale(img, 1.1, 3)
except:
# todo handle the exception
pass
if len(faces) > 0:
for x,y,w,h in faces:
temp = img[int(y):int(y+h), int(x):int(x+w)]
rotation = align_face(temp)
processed_face_48 = process_face(temp)
processed_face_x = process_face(temp, target_size=(224,224), to_gray=False)
resp.append((processed_face_48, processed_face_x , [x, y, w, h], rotation))
return resp
return None