-
Notifications
You must be signed in to change notification settings - Fork 24
Expand file tree
/
Copy pathdetector.py
More file actions
140 lines (113 loc) · 3.57 KB
/
detector.py
File metadata and controls
140 lines (113 loc) · 3.57 KB
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
from config import cv2_cascade_path
import math
class Detector:
def __init__(self):
self.face_cascade = cv2.CascadeClassifier(cv2_cascade_path + 'haarcascade_frontalface_default.xml')
self.eye_cascade = cv2.CascadeClassifier(cv2_cascade_path + 'haarcascade_eye.xml')
self.face_bb = None
self.eyes_bb = {'left':None, 'right':None}
def reset_eyes_bb(self):
self.eyes_bb = {'left':None, 'right':None}
def is_same_face_bb(self,bb1,bb2):
x1,y1,w1,h1 = bb1
x2,y2,w2,h2 = bb2
tolerance = 5
return math.fabs(w1-w2) < tolerance and math.fabs(h1-h2) < tolerance and math.fabs(x1-x2) < tolerance and math.fabs(y1-y2) < tolerance
def is_same_eye_bb(self,bb1,bb2):
x1,y1,w1,h1 = bb1
x2,y2,w2,h2 = bb2
toleranceX = 10
toleranceY = 10
toleranceW = 10
toleranceH = 10
return math.fabs(w1-w2) < toleranceW and math.fabs(h1-h2) < toleranceH and math.fabs(x1-x2) < toleranceX and math.fabs(y1-y2) < toleranceY
def get_face(self, frame):
#Find faces
faces = self.face_cascade.detectMultiScale(
frame,
scaleFactor=1.1,
minNeighbors=5,
minSize=(50, 50),
maxSize=(110, 110),
flags = cv2.cv.CV_HAAR_SCALE_IMAGE
)
#Skip frame if no face
if len(faces) != 1:
return None
face_bb = faces[0]
#Save face for first frame
if self.face_bb is None:
self.face_bb = face_bb
#Check if similar bounding box
elif self.is_same_face_bb(face_bb,self.face_bb):
#Same-ish BB, load
face_bb = self.face_bb
else:
#New BB, save and skip frame
self.face_bb = face_bb
return None
return face_bb
#Returns left eye then right (on picture)
def get_eyes(self, face):
#Find eyes in the face
eyes = self.eye_cascade.detectMultiScale(
face,
scaleFactor=1.1,
minNeighbors=5,
minSize=(60, 60),
maxSize=(100, 100),
flags = cv2.cv.CV_HAAR_SCALE_IMAGE
)
if len(eyes) != 2:
return None
left_eyeX = 999
left_eye = None
right_eye = None
#Find left and right eyes
for ex,ey,ew,eh in eyes:
#New left eye
if ex < left_eyeX:
if left_eye is not None:
right_eye = left_eye
left_eye = (ex,ey,ew,eh)
else:
left_eye = (ex,ey,ew,eh)
left_eyeX = ex
else:
if left_eye is not None:
right_eye = (ex,ey,ew,eh)
#Stabilization
eyes_bb = {'left':left_eye,'right':right_eye}
for side in ['left','right']:
#Save first frame BB
if self.eyes_bb[side] is None:
self.eyes_bb[side] = eyes_bb[side]
#Load if similar BB
elif self.is_same_eye_bb(eyes_bb[side],self.eyes_bb[side]):
eyes_bb[side] = self.eyes_bb[side]
#Changed the Bounding Box
else:
#New BB, save and skip frame
self.eyes_bb[side] = eyes_bb[side]
return None
#Get BB for cropping
xLeft, yLeft, wLeft, hLeft = eyes_bb['left']
xRight, yRight, wRight, hRight = eyes_bb['right']
focus_on_center = False
if focus_on_center:
# #Focus on the center of the eye
wLeftNew = int(wLeft*0.75)
hLeftNew = int(hLeft*0.75)
xLeftNew = int(xLeft+float(wLeft)*0.5-float(wLeftNew)*0.5)
yLeftNew = int(yLeft+float(hLeft)*0.55-float(hLeftNew)*0.45)
xLeft, yLeft, wLeft, hLeft = xLeftNew, yLeftNew, wLeftNew, hLeftNew
# #Focus on the center of the eye
wRightNew = int(wRight*0.75)
hRightNew = int(hRight*0.75)
xRightNew = int(xRight+float(wRight)*0.5-float(wRightNew)*0.5)
yRightNew = int(yRight+float(hRight)*0.55-float(hRightNew)*0.45)
xRight, yRight, wRight, hRight = xRightNew, yRightNew, wRightNew, hRightNew
left_eyeImage = face[yLeft:yLeft+hLeft, xLeft:xLeft+wLeft]
right_eyeImage = face[yRight:yRight+hRight, xRight:xRight+wRight]
return left_eyeImage, right_eyeImage