Can anyone help, I am working on an eye detection project, to detect the directions of the pupil, say left or right, it works well but whenever I use glasses it glitches, it starts to detect the pupil directions wrongly…
Here is my code below:
#for the iris(eye) detection
def iris_size(gray):
#return the percentage of space that the iris takes up on the
#surface of the eye
eye_space = gray[5:-5, 5:-5]
height, width = eye_space.shape[:2]
nb_pixels = height * width
nb_blacks = nb_pixels - cv2.countNonZero(eye_space)
return nb_blacks / nb_pixels
def image_processing(eye_frame, threshold):
#perform operations on the eye frame to isolate the iris
kernel = np.ones((3, 3), np.uint8)
new_frame = cv2.bilateralFilter(gray, 10, 15, 15)
new_frame = cv2.erode(new_frame, kernel, iterations=3)
new_frame = cv2.threshold(new_frame, threshold, 255, cv2.THRESH_BINARY)[1]
return new_frame
def find_best_threshold_value(gray):
#calibrate the pupil detection algorithm by finding the best
#binarization threshold value for the person
avg_iris_size = 0.48
trials = {}
#keep adjusting till we find the best threshold that fits the current environment
for threshold in range(5, 100, 5):
iris_frame = image_processing(gray, threshold)
trials[threshold] = iris_size(iris_frame)
best_threshold = min(trials.items(), key=(lambda p: abs(p[1] - avg_iris_size)))[0]
return best_threshold
#get eye movements
def get_gaze_ratio(eye_points, facial_landmarks):
eye_region = np.array([(facial_landmarks.part(eye_points[0]).x, facial_landmarks.part(eye_points[0]).y),
(facial_landmarks.part(eye_points[1]).x, facial_landmarks.part(eye_points[1]).y),
(facial_landmarks.part(eye_points[2]).x, facial_landmarks.part(eye_points[2]).y),
(facial_landmarks.part(eye_points[3]).x, facial_landmarks.part(eye_points[3]).y),
(facial_landmarks.part(eye_points[4]).x, facial_landmarks.part(eye_points[4]).y),
(facial_landmarks.part(eye_points[5]).x, facial_landmarks.part(eye_points[5]).y)], np.int32)
#Create a mask(a black screen/frame) to get only the eye
height, width = gray.shape[:2]
black_frame = np.zeros((height, width), np.uint8)
mask = np.full((height, width), 255, np.uint8)
#cv2.polylines(mask, [eye_region], True, 255, 2)
cv2.fillPoly(mask, [eye_region], (0, 0, 0))
#working with both eyes taking left eye into consideration
eye = cv2.bitwise_not(black_frame, gray.copy(), mask = mask)
#slicing the eye into portions and cropping it
min_x = np.min(eye_region[:, 0])
max_x = np.max(eye_region[:, 0])
min_y = np.min(eye_region[:, 1])
max_y = np.max(eye_region[:, 1])
gray_frame_eye = eye[min_y: max_y, min_x: max_x]
#add blur to reduce noise including fluctuations when a user is wearing glasses
blur_eye = cv2.GaussianBlur(gray_frame_eye, (7, 7), 0)
_, threshold_eye = cv2.threshold(blur_eye, thres_best, 255, cv2.THRESH_BINARY)
#height and width of both the left and right eye
height, width = threshold_eye.shape[:2]
#eye threshold
left_side_threshold = threshold_eye[0: height, 0: int(width / 2)]
#get only the white part of the eye(255)
left_side_white = cv2.countNonZero(left_side_threshold)
right_side_threshold = threshold_eye[0: height, int(width / 2): width]
right_side_white = cv2.countNonZero(right_side_threshold)
gaze_ratio = left_side_white / right_side_white
return gaze_ratio