Created
May 2, 2017 03:43
-
-
Save nikgens/cc3bdae1d71119ebbb8f322751e8d2dc to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# import the necessary packages | |
from __future__ import division | |
from scipy.spatial import distance as dist | |
import numpy as np | |
import time | |
import dlib | |
import cv2 | |
from collections import OrderedDict | |
# define two constants, one for the eye aspect ratio to indicate | |
# blink and then a second constant for the number of consecutive | |
# frames the eye must be below the threshold | |
EYE_AR_THRESH = 0.23 | |
EYE_AR_CONSEC_FRAMES = 35 | |
# initialize the frame counters and the total number of blinks | |
COUNTER = 0 | |
# define a dictionary that maps the indexes of the facial | |
# landmarks to specific face regions | |
FACIAL_LANDMARKS_IDXS = OrderedDict([ | |
("mouth", (48, 68)), | |
("right_eyebrow", (17, 22)), | |
("left_eyebrow", (22, 27)), | |
("right_eye", (36, 42)), | |
("left_eye", (42, 48)), | |
("nose", (27, 35)), | |
("jaw", (0, 17)) | |
]) | |
def eye_aspect_ratio(eye): | |
# compute the euclidean distances between the two sets of | |
# vertical eye landmarks (x, y)-coordinates | |
A = dist.euclidean(eye[1], eye[5]) | |
B = dist.euclidean(eye[2], eye[4]) | |
# compute the euclidean distance between the horizontal | |
# eye landmark (x, y)-coordinates | |
C = dist.euclidean(eye[0], eye[3]) | |
# compute the eye aspect ratio | |
ear = (A + B) / (2.0 * C) | |
# return the eye aspect ratio | |
return ear | |
def resize(img, width=None, height=None, interpolation=cv2.INTER_AREA): | |
global ratio | |
w, h, _ = img.shape | |
if width is None and height is None: | |
return img | |
elif width is None: | |
ratio = height / h | |
width = int(w * ratio) | |
resized = cv2.resize(img, (height, width), interpolation) | |
return resized | |
else: | |
ratio = width / w | |
height = int(h * ratio) | |
resized = cv2.resize(img, (height, width), interpolation) | |
return resized | |
def shape_to_np(shape, dtype="int"): | |
# initialize the list of (x, y)-coordinates | |
coords = np.zeros((68, 2), dtype=dtype) | |
# loop over the 68 facial landmarks and convert them | |
# to a 2-tuple of (x, y)-coordinates | |
for i in range(0, 68): | |
coords[i] = (shape.part(i).x, shape.part(i).y) | |
# return the list of (x, y)-coordinates | |
return coords | |
camera = cv2.VideoCapture(0) | |
predictor_path = 'C:\\Users\\nikgens\\Anaconda3\\pkgs\\dlib-19.4-np111py36_200\\info\\recipe\\shape_predictor_68_face_landmarks.dat' | |
print('[INFO] Downloading face detector and facial landmarks predictor...') | |
detector = dlib.get_frontal_face_detector() | |
predictor = dlib.shape_predictor(predictor_path) | |
# grab the indexes of the facial landmarks for the left and | |
# right eye, respectively | |
(lStart, lEnd) = FACIAL_LANDMARKS_IDXS["left_eye"] | |
(rStart, rEnd) = FACIAL_LANDMARKS_IDXS["right_eye"] | |
vs = cv2.VideoCapture(0) | |
fileStream = True | |
time.sleep(1.0) | |
# loop over frames from the video stream | |
while True: | |
# grab the frame from the threaded video file stream, resize | |
# it, and convert it to grayscale | |
# channels) | |
ret, frame = camera.read() | |
if ret == False: | |
print('Failed to capture frame from camera. Check camera index in cv2.VideoCapture(0) \n') | |
break | |
frame_resized = resize(frame, width=240) | |
frame_gray = cv2.cvtColor(frame_resized, cv2.COLOR_BGR2GRAY) | |
# detect faces in the grayscale frame | |
rects = detector(frame_gray, 0) | |
# loop over the face detections | |
for rect in rects: | |
# determine the facial landmarks for the face region, then | |
# convert the facial landmark (x, y)-coordinates to a NumPy | |
# array | |
shape = predictor(frame_gray, rect) | |
shape = shape_to_np(shape) | |
# extract the left and right eye coordinates, then use the | |
# coordinates to compute the eye aspect ratio for both eyes | |
leftEye = shape[lStart:lEnd] | |
rightEye = shape[rStart:rEnd] | |
leftEAR = eye_aspect_ratio(leftEye) | |
rightEAR = eye_aspect_ratio(rightEye) | |
# take the minimum eye aspect ratio | |
ear = min([leftEAR,rightEAR]) | |
# check to see if the eye aspect ratio is below the blink | |
# threshold, and if so, increment the blink frame counter | |
if ear < EYE_AR_THRESH: | |
COUNTER += 1 | |
if 100 >= COUNTER >= EYE_AR_CONSEC_FRAMES: | |
cv2.putText(frame, "Warning! Seems he is trying to sleep", (10, 30), | |
cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 255, 0), 2) | |
if COUNTER > 100: | |
cv2.putText(frame, "ALARM!!! ALARM!!! HE\'S SLEEPING", (10, 30), | |
cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 2) | |
else: | |
# reset the eye frame counter | |
COUNTER = 0 | |
for (x, y) in np.concatenate((leftEye, rightEye), axis=0): | |
cv2.circle(frame, (int(x / ratio), int(y / ratio)), 2, (255, 255, 255), -1) | |
# show the frame | |
cv2.imshow("Frame", frame) | |
key = cv2.waitKey(1) & 0xFF | |
# if the `q` key was pressed, break from the loop | |
if key == ord("q"): | |
break | |
# close all | |
cv2.destroyAllWindows() | |
vs.release() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hello @nikgens
The alarm doesn't work, how to activate it?