Skip to content

Commit

Permalink
[added] Eye Blink detector
Browse files Browse the repository at this point in the history
  • Loading branch information
varadhodiyil committed Apr 16, 2018
1 parent 750b5dc commit e8ad80a
Show file tree
Hide file tree
Showing 6 changed files with 141 additions and 57 deletions.
111 changes: 111 additions & 0 deletions face_api/face_api/core/model/eye_detect.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@

import argparse
import os
import time

import dlib
import imutils
import numpy as np
from imutils import face_utils
from imutils.video import FileVideoStream, VideoStream
from scipy.spatial import distance as dist

import cv2

DEBUG = False


class EyeBlinkDetector():

def __init__(self):
print("[INFO] loading facial landmark predictor...")
path = os.path.dirname(os.path.abspath(__file__))
self.predictor = dlib.shape_predictor(
os.path.join(path, 'models/dlib_model.dat'))

def eye_aspect_ratio(self, eye):

A = dist.euclidean(eye[1], eye[5])
B = dist.euclidean(eye[2], eye[4])

C = dist.euclidean(eye[0], eye[3])
ear = (A + B) / (2.0 * C)

return ear

def get_num_blinks(self, media_file):

EYE_AR_THRESH = 0.3
EYE_AR_CONSEC_FRAMES = 3

COUNTER = 0
TOTAL = 0

detector = dlib.get_frontal_face_detector()

(lStart, lEnd) = face_utils.FACIAL_LANDMARKS_IDXS["left_eye"]
(rStart, rEnd) = face_utils.FACIAL_LANDMARKS_IDXS["right_eye"]

print("[INFO] starting video stream thread...")
vs = FileVideoStream(media_file).start()
fileStream = True
# vs = VideoStream(src=0).start()
# vs = VideoStream().start()
# vs = cv2.VideoCapture(0)
# fileStream = False
# time.sleep(1.0)

# loop over frames from the video stream
while True:
k = cv2.waitKey(30) & 0xff

if k == 27:
break
if fileStream and not vs.more():
break
frame = vs.read()

rects = detector(frame, 0)
for rect in rects:

shape = self.predictor(frame, rect)
shape = face_utils.shape_to_np(shape)
leftEye = shape[lStart:lEnd]
rightEye = shape[rStart:rEnd]
leftEAR = self.eye_aspect_ratio(leftEye)
rightEAR = self.eye_aspect_ratio(rightEye)

ear = (leftEAR + rightEAR) / 2.0
leftEyeHull = cv2.convexHull(leftEye)
rightEyeHull = cv2.convexHull(rightEye)
cv2.drawContours(frame, [leftEyeHull], -1, (0, 255, 0), 1)
cv2.drawContours(frame, [rightEyeHull], -1, (0, 255, 0), 1)

if ear < EYE_AR_THRESH:
COUNTER += 1
else:
if COUNTER >= EYE_AR_CONSEC_FRAMES:
TOTAL += 1
COUNTER = 0

if DEBUG:
cv2.putText(frame, "Blinks: {}".format(TOTAL), (10, 30),
cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
cv2.putText(frame, "EAR: {:.2f}".format(ear), (300, 30),
cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)

if DEBUG:
cv2.imshow("Frame", frame)
vs.stop()
cv2.destroyAllWindows()
return TOTAL


if __name__ == '__main__':
ey = EyeBlinkDetector()
ap = argparse.ArgumentParser()

ap.add_argument("-v", "--video", type=str, default="1.mp4",
help="path to input video file")
args = vars(ap.parse_args())
print ey.get_num_blinks(args['video'])
2 changes: 1 addition & 1 deletion face_api/face_api/core/model/predict.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ def sample_prediction(test_im,_labels_):
return test_pred[0]
test_img = cv2.imread('temp.jpg')
test_img = cv2.cvtColor(test_img, cv2.COLOR_BGR2GRAY)
dg = DataSetGenerator("/home/madhan/Documents/skalenow/face_reco/train_faces")
dg = DataSetGenerator("train_faces")
labels = dg.load_labels()
_np_labels = list()
for i in range(len(labels)):
Expand Down
40 changes: 0 additions & 40 deletions face_api/face_api/core/model/verify_user.1.py

This file was deleted.

13 changes: 10 additions & 3 deletions face_api/face_api/core/model/verify_user.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
from DataSetGenerator import DataSetGenerator
from opencv_utils import OpenCVHelper
from predictor import Predictor
from eye_detect import EyeBlinkDetector

eye_p = EyeBlinkDetector()
path = os.path.dirname(os.path.abspath(__file__))
class VerifyUser:
def __init__(self):
Expand All @@ -20,6 +23,10 @@ def get_results(self,file_in):
return False

""" ------------------- Loading and process the video file ----------------- """
num_blinks = eye_p.get_num_blinks(file_in)
print "Num Blinks : %d " % num_blinks
if num_blinks <=0:
return None , "No Eye Blink found. !"
cap = cv2.VideoCapture(file_in)
results = list()
while True:
Expand All @@ -35,8 +42,8 @@ def get_results(self,file_in):
if len(results) > 0:
r = sum(results) / float(len(results))
r = int(abs(r))
return self.dg.data_labels[r]
return None
return self.dg.data_labels[r] , True
return None , "No Face Found !"
if __name__ == '__main__':
v = VerifyUser()
print v.get_results("/home/madhan/Documents/skalenow/face_api/face_api/core/model/media/verify/1.mp4")
print v.get_results("media/verify/1.mp4")
31 changes: 18 additions & 13 deletions face_api/face_api/core/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from django.shortcuts import get_object_or_404
from rest_framework import status
from rest_framework.generics import GenericAPIView
from rest_framework.parsers import MultiPartParser , JSONParser
from rest_framework.parsers import JSONParser, MultiPartParser
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response

Expand Down Expand Up @@ -68,22 +68,25 @@ def post(self, request,*args,**kwargs):
if s.is_valid():
file_obj = s.validated_data['data']
file_type = file_obj.content_type.split('/')[0]
print file_type
if file_type == "video" or file_type == "application":
fs = FileSystemStorage()
path = os.path.join('verify',file_obj.name)
filename = fs.save(path, file_obj)
_path = os.path.join(MEDIA_ROOT,filename)
print _path
result['status'] = True
v_user = VerifyUser()

user = v_user.get_results(_path)
user = models.Users.objects.filter(id=user)
user = get_object_or_404(user)

token = models.Token(user=user).save()
result['token'] = token.key
v_user = VerifyUser()

user , status_ = v_user.get_results(_path)
print user , status_
if user:
result['status'] = True
user = models.Users.objects.filter(id=user)
user = get_object_or_404(user)
token = models.Token(user=user).save()
result['token'] = token.key
result['status'] = status_
result['status'] = False
return Response(result)
else:
result['status'] = False
Expand Down Expand Up @@ -122,16 +125,18 @@ def post(self,request,*args,**kwargs):
print _path
result['status'] = True
v_user = VerifyUser()
r_user = v_user.get_results(_path)
r_user , status_ = v_user.get_results(_path)
print r_user , user.__str__()
if r_user == user.__str__():
s.validated_data.pop("data")
s.save()
result['status'] = True
result['result'] = status_
return Response(result)
else:
result['status'] = False
result['error'] = "Invalid User"
result['result'] = status_
return Response(result)
else:
result['status'] = False
Expand Down Expand Up @@ -163,12 +168,13 @@ def post(self, request,*args,**kwargs):
result['status'] = True
v_user = VerifyUser()

user = v_user.get_results(_path)
user , status_ = v_user.get_results(_path)
user = models.Users.objects.filter(id=user)
user = get_object_or_404(user)

token = models.Token(user=user).save()
result['token'] = token.key
result['result'] = status_
return Response(result)
else:
result['status'] = False
Expand All @@ -178,4 +184,3 @@ def post(self, request,*args,**kwargs):
result['status'] = False
result['errors'] = s.errors
return Response(result, status=status.HTTP_400_BAD_REQUEST)

1 change: 1 addition & 0 deletions face_api/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ mysqlclient==1.3.4
numpy==1.14.2
scipy-1.0.1
python-dateutil
imutils

0 comments on commit e8ad80a

Please sign in to comment.