Eye Tracking using OpenCV

Ramji Balasubramanian
Analytics Vidhya
Published in
3 min readDec 26, 2020

During my early 2000's my father used to drive me to my home town for vacation. which will take approximately 8 hours from were I live. During our journey my primary role is to sit beside him and wake him up whenever his eyes getting closed. What if I am not near him? Isn’t it scary? Yeah it was. After reading this case study from OpenCV where we can use a small camera to keep tracking your eyes, felt happy and imagined about helpful it will be to avoid lots of accidents on highways.

Steps to track your eye

  1. Detect your face
  2. Crop the face region and detect eyes in face region
  3. Keep tracking the eye region

Code Snippet

If you are trying in your own video the the scale factor and min Neighbors are the we need to tune to get the better result.

# import the necessary packages
import cv2
class EyeTracker:
def __init__(self, faceCascadePath, eyeCascadePath):
# load the face and eye detector
self.faceCascade = cv2.CascadeClassifier(faceCascadePath)
self.eyeCascade = cv2.CascadeClassifier(eyeCascadePath)
def track(self, image):
# detect faces in the image and initialize the list of
# rectangles containing the faces and eyes
faceRects = self.faceCascade.detectMultiScale(image,
scaleFactor = 1.1, minNeighbors = 5, minSize = (30,30),
flags = cv2.CASCADE_SCALE_IMAGE)
rects = []
# loop over the face bounding boxes
for (fX, fY, fW, fH) in faceRects:
# extract the face ROI and update the list of
# bounding boxes
faceROI = image[fY:fY + fH, fX:fX + fW]
rects.append((fX, fY, fX + fW, fY + fH))

# detect eyes in the face ROI
eyeRects = self.eyeCascade.detectMultiScale(faceROI,
scaleFactor = 1.1, minNeighbors = 10, minSize = (20, 20),
flags = cv2.CASCADE_SCALE_IMAGE)
# loop over the eye bounding boxes
for (eX, eY, eW, eH) in eyeRects:
# update the list of boounding boxes
rects.append(
(fX + eX, fY + eY, fX + eX + eW, fY + eY + eH))
# return the rectangles representing bounding
# boxes around the faces and eyes
return rects

So now we have create a class which will detect faces and eyes from a video. But if we are sending video of different sizes the parameter needs to be changed often. To overcome this we can do a preprocessing on the input image, such that the eye tracker class will be called after converting to a certain format.

# USAGE
# python eyetracking.py — face cascades/haarcascade_frontalface_default.xml — eye cascades/haarcascade_eye.xml — video video/adrian_eyes.mov
# python eyetracking.py — face cascades/haarcascade_frontalface_default.xml — eye cascades/haarcascade_eye.xml
# import the necessary packages
from pyimagesearch.eyetracker import EyeTracker
from pyimagesearch import imutils
import argparse
import cv2
# construct the argument parse and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument(“-f”, “ — face”, required = True,
help = “path to where the face cascade resides”)
ap.add_argument(“-e”, “ — eye”, required = True,
help = “path to where the eye cascade resides”)
ap.add_argument(“-v”, “ — video”,
help = “path to the (optional) video file”)
args = vars(ap.parse_args())
# construct the eye tracker
et = EyeTracker(args[“face”], args[“eye”])
# if a video path was not supplied, grab the reference
# to the gray
if not args.get(“video”, False):
camera = cv2.VideoCapture(0)
# otherwise, load the video
else:
camera = cv2.VideoCapture(args[“video”])
# keep looping
while True:
# grab the current frame
(grabbed, frame) = camera.read()
# if we are viewing a video and we did not grab a
# frame, then we have reached the end of the video
if args.get(“video”) and not grabbed:
break
# resize the frame and convert it to grayscale
frame = imutils.resize(frame, width = 300)
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# detect faces and eyes in the image
rects = et.track(gray)
# loop over the face bounding boxes and draw them
for rect in rects:
cv2.rectangle(frame, (rect[0], rect[1]), (rect[2], rect[3]), (0, 255, 0), 2)
# show the tracked eyes and face
cv2.imshow(“Tracking”, frame)
# if the ‘q’ key is pressed, stop the loop
if cv2.waitKey(1) & 0xFF == ord(“q”):
break
# cleanup the camera and close any open windows
camera.release()
cv2.destroyAllWindows(

Reference:

OpenCV- Basics Bundle by Adrian

link to code: https://github.com/RamjiB/Eye-Tracking

--

--