Owleye / codes /see_data.py
owleyetracker's picture
Upload 45 files
b4c5d36 verified
"""This module is for seeing the inputs and the outputs."""
import cv2
from codes.base import eyeing as ey
import time
import matplotlib.pyplot as plt
import numpy as np
import os
import math
from openpyxl import load_workbook
class See(object):
running = True
@staticmethod
def data_features(num, target_fol=ey.CLB):
"""
Seeing the inputs in each one of the folders
Parameters:
num: subject number
target_fol: targeted folder
Returns:
None
"""
sbj_dir = ey.create_dir([ey.subjects_dir, f"{num}"])
if target_fol == ey.CLB:
target_dir = ey.create_dir([sbj_dir, ey.CLB])
data = ey.load(target_dir, [ey.X1, ey.X2, ey.Y])
elif target_fol == ey.IO:
target_dir = ey.create_dir([sbj_dir, ey.IO])
data = ey.load(target_dir, [ey.X1, ey.X2, ey.Y])
elif target_fol == ey.SMP:
target_dir = ey.create_dir([sbj_dir, ey.SMP])
data = ey.load(target_dir, [ey.X1, ey.X2, ey.T])
elif target_fol == ey.ACC:
target_dir = ey.create_dir([sbj_dir, ey.ACC])
data = ey.load(target_dir, [ey.X1, ey.X2, ey.T, ey.Y])
elif target_fol == ey.LTN:
target_dir = ey.create_dir([sbj_dir, ey.LTN])
data = ey.load(target_dir, [ey.X1, ey.X2, ey.T])
else:
data = None
print("The folder isn't valid!!")
quit()
win_name = "Eyes"
cv2.namedWindow(win_name)
if len(ey.monitors) == 1:
cv2.moveWindow(win_name, int(ey.monitors[0].width / 2), int(ey.monitors[0].height / 2))
else:
cv2.moveWindow(win_name, ey.monitors[0].width + int(ey.monitors[0].width / 2), int(ey.monitors[0].height / 2))
x1 = data[0]
print(f"Number of vectors : {len(x1)}")
time.sleep(2)
i = 0
for (k, x1_vec) in enumerate(x1):
for (s, img) in enumerate(x1_vec):
d = []
for (j, _) in enumerate(data):
if j == 0:
continue
d.append(data[j][k][s])
if True: #i % 10 == 0:
print(f"{i}, {d}")
cv2.imshow(win_name, img)
q = cv2.waitKey(20)
if q == ord('q') or q == ord('Q'):
break
i += 1
if q == ord('q') or q == ord('Q'):
break
cv2.destroyAllWindows()
def pixels_smp(self, num, n_monitors_data=len(ey.monitors), show_in_all_monitors=False, win_size=(1280,720), show_fixations=False):
"""
See the eye viewpoint of the user during sampling.
Parameters:
num: subject number
n_monitors_data: The number of monitors while the data was collecting.
show_in_all_monitors: Just for the moment that we have more than one monitor. So we tune the parameters to show the data in all of them
win_size: size of the appeared window
show_fixations: It shows the fixations
Returns:
None
"""
little_win = False
smp_dir = ey.create_dir([ey.subjects_dir, f"{num}", ey.SMP])
try:
sheet_et = load_workbook(smp_dir + "eye_track.xlsx")["Sheet"]
prd_et = []
for i in range(3,sheet_et.max_row+1):
et_splited = sheet_et[f"C{i}"].value[1:-1].split(',')
prd_et.append([float(sheet_et[f"A{i}"].value), float(et_splited[0]), float(et_splited[1])])
prd_et = np.array(prd_et)
if show_fixations:
sheet_fxn = load_workbook(smp_dir + "fixations.xlsx")["Sheet"]
fixations = []
for i in range(3, sheet_fxn.max_row+1):
fxn_splited = sheet_fxn[f"D{i}"].value[1:-1].split(',')
fixations.append([float(sheet_fxn[f"A{i}"].value), float(sheet_fxn[f"C{i}"].value),
float(fxn_splited[0]), float(fxn_splited[1])])
fixations = np.array(fixations)
if show_in_all_monitors:
win_names = []
for (i, m) in enumerate(ey.monitors):
win_name = f"Calibration-{i}"
ey.big_win(win_name, i * m.width)
win_names.append(win_name)
elif (n_monitors_data == 1):
win_name = "Calibration"
ey.big_win(win_name, math.floor(len(ey.monitors)/2)*ey.monitors[0].width)
else:
win_name = "Calibration"
little_win = True
for prd1 in prd_et:
t0 = prd1[0]
fxn_exist = False
if show_fixations:
time_comparison = t0 - fixations[:, 0]
time_comparison[time_comparison<0] = 1000
matched_t_fxn_arg = time_comparison.argmin()
if (t0 > fixations[matched_t_fxn_arg, 0]) and (t0 < (fixations[matched_t_fxn_arg, 0]+fixations[matched_t_fxn_arg, 1])):
fxn_exist = True
prd0 = prd1[1:]
tx0 = [[f"time: {t0} sec", (0.05, 0.25), 1, ey.GREEN, 2]]
if show_in_all_monitors:
y_prd_show = [None] * len(ey.monitors)
texts = y_prd_show.copy()
texts[math.floor(len(ey.monitors) / 2)] = tx0
pw_prd = prd0[0] * n_monitors_data
for (i, _) in enumerate(ey.monitors):
if prd0[0] != -1:
win_color = ey.WHITE
if i != 1:
t0 = None
if (pw_prd > i) and (pw_prd < (i + 1)):
y_prd_show[i] = prd0
y_prd_show[i][0] = pw_prd - i
else:
prd0 = None
win_color = ey.GRAY
ey.show_clb_win(win_names[i], pnt_prd=y_prd_show[i], texts=texts[i], win_color=win_color)
else:
if prd0[0] != -1:
win_color = ey.WHITE
else:
prd0 = None
win_color = ey.GRAY
if little_win:
if fxn_exist:
ey.show_clb_win(win_name, pnt=fixations[matched_t_fxn_arg,2:],
pnt_prd=prd0, texts=tx0, win_color=win_color, win_size=win_size, pnt_color=ey.RED)
else:
ey.show_clb_win(win_name, pnt_prd=prd0, texts=tx0, win_color=win_color, win_size=win_size)
cv2.moveWindow(win_name, 0, 0)
else:
if fxn_exist:
ey.show_clb_win(win_name, pnt=fixations[matched_t_fxn_arg,2:],
pnt_prd=prd0, texts=tx0, win_color=win_color, pnt_color=ey.RED)
else:
ey.show_clb_win(win_name, pnt_prd=prd0, texts=tx0, win_color=win_color)
q = cv2.waitKey(50)
if q == ord('q') or q == ord('Q'):
break
if not self.running:
break
cv2.destroyAllWindows()
except FileNotFoundError:
print(f"Data does not exist in {smp_dir}")
def pixels_acc(self, num, n_monitors_data=len(ey.monitors), show_in_all_monitors=False):
"""
See the eye viewpoint of the user during testing.
Parameters:
num: subject number
n_monitors_data: The number of monitors while the data was collecting.
show_in_all_monitors: Just for the moment that we have more than one monitor. So we tune the parameters to show the data in all of them
Returns:
None
"""
acc_dir = ey.create_dir([ey.subjects_dir, f"{num}", ey.ACC])
if ey.file_existing(acc_dir, 'y_mdf.pickle'):
[y, y_prd] = ey.load(acc_dir, ['y_mdf', 'y_prd_mdf'])
if show_in_all_monitors:
win_names = []
for (i, m) in enumerate(ey.monitors):
win_name = f"Calibration-{i}"
ey.big_win(win_name, i * m.width)
win_names.append(win_name)
else:
win_name = "Calibration"
ey.big_win(win_name, math.floor(len(ey.monitors) / 2)*ey.monitors[0].width)
for (y0, y_prd0) in zip(y, y_prd):
if show_in_all_monitors:
y_show = [None] * len(ey.monitors)
y_prd_show = [None] * len(ey.monitors)
pw = y0[0] * n_monitors_data
pw_prd = y_prd0[0] * n_monitors_data
for (i, _) in enumerate(ey.monitors):
if (pw > i) and (pw < (i + 1)):
y_show[i] = y0
y_show[i][0] = pw - i
if (pw_prd > i) and (pw_prd < (i + 1)):
y_prd_show[i] = y_prd0
y_prd_show[i][0] = pw_prd - i
ey.show_clb_win(win_names[i], pnt=y_show[i], pnt_prd=y_prd_show[i], win_color=ey.WHITE, pnt_color=ey.RED)
else:
ey.show_clb_win(win_name, pnt=y0, pnt_prd=y_prd0, win_color=ey.WHITE, pnt_color=ey.RED)
q = cv2.waitKey(50)
if q == ord('q') or q == ord('Q') or q == 27:
break
if not self.running:
break
cv2.destroyAllWindows()
else:
print(f"Data does not exist in {acc_dir}")
@staticmethod
def blinks_plot(num, threshold=ey.DEFAULT_BLINKING_THRESHOLD, target_fol="er"):
"""
Plotting the eyes aspect ratio (EAR) vector to tune threshold
Parameters:
num: subject number
threshold: the threshold of ear velocity
target_fol: targeted folder
Returns:
None
"""
sbj_dir = ey.create_dir([ey.subjects_dir, f"{num}"])
if target_fol == ey.ER:
target_dir = ey.create_dir([sbj_dir, ey.ER])
elif target_fol == ey.CLB:
target_dir = ey.create_dir([sbj_dir, ey.CLB])
elif target_fol == ey.SMP:
target_dir = ey.create_dir([sbj_dir, ey.SMP])
elif target_fol == ey.ACC:
target_dir = ey.create_dir([sbj_dir, ey.ACC])
else:
print("The folder isn't valid!!")
quit()
er_dir = ey.create_dir([sbj_dir, ey.ER])
t_mat, eyes_ratio_mat = ey.load(target_dir, [ey.T, ey.ER])
threshold = ey.get_threshold(er_dir, threshold)
print(f"Blinking threshold is {threshold}")
eyes_ratio_v_mat, _, eyes_ratio_v_blink_mat = ey.get_blinking(t_mat, eyes_ratio_mat, threshold)
if len(eyes_ratio_v_mat) > 1:
eyes_ratio_v_vec = eyes_ratio_v_mat[0]
eyes_ratio_v_blink_vec = eyes_ratio_v_blink_mat[0]
for (i, erv) in enumerate(eyes_ratio_v_mat):
if i == 0:
continue
eyes_ratio_v_vec = np.concatenate([eyes_ratio_v_vec, erv])
eyes_ratio_v_blink_vec = np.concatenate([eyes_ratio_v_blink_vec, eyes_ratio_v_blink_mat[i]])
else:
eyes_ratio_v_vec = eyes_ratio_v_mat[0]
eyes_ratio_v_blink_vec = eyes_ratio_v_blink_mat[0]
# print(eyes_ratio_v_vec)
plt.figure()
plt.plot(eyes_ratio_v_vec)
plt.plot(eyes_ratio_v_blink_vec)
plt.title(f"Velocity of Eyes Ratio ({target_fol})")
plt.xlabel("# of Sample")
plt.ylabel("ER/sec")
blink_img_dir = target_dir + 'blinking.png'
plt.savefig(blink_img_dir, dpi=300, bbox_inches='tight')
blink_img = cv2.imread(blink_img_dir)
cv2.imshow("Blinking", blink_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
os.remove(blink_img_dir)
def user_face(self, num, threshold="d", save_threshold=False):
"""
Show the user's face to tune blinking threshold.
Parameters:
num: subject number
threshold: the blinking threshold
save_threshold: save the tuned threshold
Returns:
None
"""
scaling_frame = 5
sbj_dir = ey.create_dir([ey.subjects_dir, f"{num}"])
smp_dir = ey.create_dir([sbj_dir, ey.SMP])
er_dir = ey.create_dir([sbj_dir, ey.ER])
threshold = ey.get_threshold(er_dir, threshold)
if save_threshold:
ey.save([threshold], er_dir, ["oth_usr"])
print(f"Blinking threshold is {threshold}")
if ey.file_existing(smp_dir, ey.T+".pickle"):
t_mat, face_mat, eyes_ratio_mat = ey.load(smp_dir, [ey.T, ey.FV, ey.ER])
eyes_ratio_v_mat = ey.get_blinking(t_mat, eyes_ratio_mat)[0]
face_vec = face_mat[0]
vec120_len, fh, fw = face_vec.shape[:-1]
little_vec_len = int(vec120_len / 10)
before_len = int(2 * little_vec_len / 3)
after_len = int(little_vec_len - before_len)
eyes_ratio_v_vec = eyes_ratio_v_mat[0][:vec120_len]
min_eyes_ratio_v, max_eyes_ratio_v = eyes_ratio_v_vec.min(), eyes_ratio_v_vec.max()
new_fw, new_fh = fw*scaling_frame, fh*scaling_frame
shift_edge = int(new_fh / 90.0)
red_area_h = int(0.85 * fh)
red_area_w = int(0.3 * fw)
thr_in_img_y = fh - int((fh / (max_eyes_ratio_v - min_eyes_ratio_v)) * (threshold - min_eyes_ratio_v))
zero_in_img_y = fh - int((fh / (max_eyes_ratio_v - min_eyes_ratio_v)) * (0.0 - min_eyes_ratio_v))
for i, fr in enumerate(face_vec):
fr = cv2.resize(fr, (new_fw, new_fh),interpolation=cv2.INTER_AREA)
frb = fr[-(fh+shift_edge):, :, :]
frb[:, :, 0:2] = 200
for j in range(i-before_len, i+after_len):
if (j>0) and (j<vec120_len):
if j != i:
marker_color = (0, 0, 255)
marker_size = 5
else:
marker_color = (0, 0, 0)
marker_size = 8
eye_ratio_in_img_x = int(j / vec120_len * new_fw)
eye_ratio_in_img_y = fh - int((fh / (max_eyes_ratio_v - min_eyes_ratio_v)) * (eyes_ratio_v_vec[j] - min_eyes_ratio_v))
frb = cv2.circle(frb, (eye_ratio_in_img_x, eye_ratio_in_img_y+shift_edge), marker_size, marker_color, cv2.FILLED)
frb = cv2.line(frb, (0, thr_in_img_y+shift_edge), (new_fw, thr_in_img_y+shift_edge), (0, 0, 0), 2)
frb = cv2.line(frb, (0, 0), (new_fw, 0), (0, 0, 0), 10)
frb = cv2.line(frb, (0, fh+shift_edge), (new_fw, fh+shift_edge), (0, 0, 0), 10)
frb = cv2.line(frb, (0, zero_in_img_y+shift_edge), (new_fw, zero_in_img_y+shift_edge), (53, 18, 80), 1)
frb = cv2.putText(frb, "erv = 0", (10, zero_in_img_y), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 81, 140), 2)
frb = cv2.putText(frb, f"erv = {threshold}", (10, thr_in_img_y), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 81, 140), 2)
fr[new_fh-(fh+shift_edge):, :, :] = frb
if eyes_ratio_v_vec[i] > threshold:
fr[-(fh+red_area_h):-fh, :, 2] = 255
fr[:red_area_h, :, 2] = 255
fr[:-fh, :red_area_w, 2] = 255
fr[:-fh, -red_area_w:, 2] = 255
win_name = "User"
if len(ey.monitors) == 1:
x_disp = 0
else:
x_disp = ey.monitors[0].width
ey.big_win(win_name, x_disp)
cv2.imshow(win_name, fr)
q = cv2.waitKey(100)
if q == ord('q') or q == ord('Q'):
break
i += 1
cv2.destroyAllWindows()
else:
print(f"Data does not exist in {smp_dir}")