1
+ from scipy .spatial import distance as dist
2
+ from imutils .video import FileVideoStream
3
+ from imutils .video import VideoStream
4
+ from imutils import face_utils
5
+ import numpy as np
6
+ import argparse
7
+ import imutils
8
+ import time
9
+ import dlib
10
+ import cv2
11
+
12
+ def eye_aspect_ratio (eye ):
13
+ A = dist .euclidean (eye [1 ], eye [5 ])
14
+ B = dist .euclidean (eye [2 ], eye [4 ])
15
+ C = dist .euclidean (eye [0 ], eye [3 ])
16
+
17
+ ear = (A + B ) / (2.0 * C )
18
+ return ear
19
+
20
+ ap = argparse .ArgumentParser ()
21
+ ap .add_argument ("-p" , "--shape-predictor" , required = True ,
22
+ help = "path to facial landmark predictor" )
23
+ ap .add_argument ("-v" , "--video" , type = str , default = "" ,
24
+ help = "path to input video file" )
25
+ args = vars (ap .parse_args ())
26
+
27
+ EYE_AR_THRESH = 0.3
28
+ EYE_AR_CONSEC_FRAMES = 3
29
+
30
+ COUNTER = 0
31
+ TOTAL = 0
32
+
33
+ print ("[INFO] loading facial landmark predictor..." )
34
+ detector = dlib .get_frontal_face_detector ()
35
+ predictor = dlib .shape_predictor (args ["shape_predictor" ])
36
+
37
+ (lStart , lEnd ) = face_utils .FACIAL_LANDMARKS_IDXS ["left_eye" ]
38
+ (rStart , rEnd ) = face_utils .FACIAL_LANDMARKS_IDXS ["right_eye" ]
39
+
40
+ print ("[INFO] starting video stream thread..." )
41
+ vs = FileVideoStream (args ["video" ]).start ()
42
+ fileStream = True
43
+ vs = VideoStream (src = 0 ).start ()
44
+ fileStream = False
45
+ time .sleep (1.0 )
46
+
47
+ while True :
48
+ if fileStream and not vs .more ():
49
+ break
50
+
51
+ frame = vs .read ()
52
+ frame = imutils .resize (frame , width = 450 )
53
+ gray = cv2 .cvtColor (frame , cv2 .COLOR_BGR2GRAY )
54
+
55
+ rects = detector (gray , 0 )
56
+
57
+ for rect in rects :
58
+ shape = predictor (gray , rect )
59
+ shape = face_utils .shape_to_np (shape )
60
+
61
+ leftEye = shape [lStart :lEnd ]
62
+ rightEye = shape [rStart :rEnd ]
63
+ leftEAR = eye_aspect_ratio (leftEye )
64
+ rightEAR = eye_aspect_ratio (rightEye )
65
+
66
+ ear = (leftEAR + rightEAR ) / 2.0
67
+
68
+ leftEyeHull = cv2 .convexHull (leftEye )
69
+ rightEyeHull = cv2 .convexHull (rightEye )
70
+ cv2 .drawContours (frame , [leftEyeHull ], - 1 , (0 , 255 , 0 ), 1 )
71
+ cv2 .drawContours (frame , [rightEyeHull ], - 1 , (0 , 255 , 0 ), 1 )
72
+
73
+ if ear < EYE_AR_THRESH :
74
+ COUNTER += 1
75
+
76
+ else :
77
+ if COUNTER >= EYE_AR_CONSEC_FRAMES :
78
+ TOTAL += 1
79
+
80
+ COUNTER = 0
81
+
82
+ cv2 .putText (frame , "Blinks: {}" .format (TOTAL ), (10 , 30 ),
83
+ cv2 .FONT_HERSHEY_SIMPLEX , 0.7 , (0 , 0 , 255 ), 2 )
84
+ cv2 .putText (frame , "EAR: {:.2f}" .format (ear ), (300 , 30 ),
85
+ cv2 .FONT_HERSHEY_SIMPLEX , 0.7 , (0 , 0 , 255 ), 2 )
86
+
87
+ cv2 .imshow ("Frame" , frame )
88
+ key = cv2 .waitKey (1 ) & 0xFF
89
+
90
+ if key == ord ("q" ):
91
+ break
92
+
93
+ cv2 .destroyAllWindows ()
94
+ vs .stop ()
0 commit comments