mirror of
https://github.com/EyeTrackVR/EyeTrackVR.git
synced 2025-11-04 14:39:42 +08:00
commit
91463707b9
176
EyeTrackApp/enums.py
Normal file
176
EyeTrackApp/enums.py
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import types
|
||||||
|
from collections import namedtuple
|
||||||
|
from typing import Any, ClassVar, Dict, List, Optional, TYPE_CHECKING, Tuple, Type, TypeVar, Iterator, Mapping
|
||||||
|
|
||||||
|
__all__ = (
|
||||||
|
'Enum',
|
||||||
|
# 'EyeId',
|
||||||
|
'EyeLR',
|
||||||
|
)
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from typing_extensions import Self
|
||||||
|
|
||||||
|
|
||||||
|
def _create_value_cls(name: str, comparable: bool):
|
||||||
|
# All the type ignores here are due to the type checker being unable to recognise
|
||||||
|
# Runtime type creation without exploding.
|
||||||
|
cls = namedtuple('_EnumValue_' + name, 'name value')
|
||||||
|
cls.__repr__ = lambda self: f'<{name}.{self.name}: {self.value!r}>' # type: ignore
|
||||||
|
cls.__str__ = lambda self: f'{name}.{self.name}' # type: ignore
|
||||||
|
if comparable:
|
||||||
|
cls.__le__ = lambda self, other: isinstance(other, self.__class__) and self.value <= other.value # type: ignore
|
||||||
|
cls.__ge__ = lambda self, other: isinstance(other, self.__class__) and self.value >= other.value # type: ignore
|
||||||
|
cls.__lt__ = lambda self, other: isinstance(other, self.__class__) and self.value < other.value # type: ignore
|
||||||
|
cls.__gt__ = lambda self, other: isinstance(other, self.__class__) and self.value > other.value # type: ignore
|
||||||
|
return cls
|
||||||
|
|
||||||
|
|
||||||
|
def _is_descriptor(obj):
|
||||||
|
return hasattr(obj, '__get__') or hasattr(obj, '__set__') or hasattr(obj, '__delete__')
|
||||||
|
|
||||||
|
|
||||||
|
class EnumMeta(type):
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
__name__: ClassVar[str]
|
||||||
|
_enum_member_names_: ClassVar[List[str]]
|
||||||
|
_enum_member_map_: ClassVar[Dict[str, Any]]
|
||||||
|
_enum_value_map_: ClassVar[Dict[Any, Any]]
|
||||||
|
|
||||||
|
def __new__(cls, name: str, bases: Tuple[type, ...], attrs: Dict[str, Any], *, comparable: bool = False) -> Self:
|
||||||
|
value_mapping = {}
|
||||||
|
member_mapping = {}
|
||||||
|
member_names = []
|
||||||
|
|
||||||
|
value_cls = _create_value_cls(name, comparable)
|
||||||
|
for key, value in list(attrs.items()):
|
||||||
|
is_descriptor = _is_descriptor(value)
|
||||||
|
if key[0] == '_' and not is_descriptor:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Special case classmethod to just pass through
|
||||||
|
if isinstance(value, classmethod):
|
||||||
|
continue
|
||||||
|
|
||||||
|
if is_descriptor:
|
||||||
|
setattr(value_cls, key, value)
|
||||||
|
del attrs[key]
|
||||||
|
continue
|
||||||
|
|
||||||
|
try:
|
||||||
|
new_value = value_mapping[value]
|
||||||
|
except KeyError:
|
||||||
|
new_value = value_cls(name=key, value=value)
|
||||||
|
value_mapping[value] = new_value
|
||||||
|
member_names.append(key)
|
||||||
|
|
||||||
|
member_mapping[key] = new_value
|
||||||
|
attrs[key] = new_value
|
||||||
|
|
||||||
|
attrs['_enum_value_map_'] = value_mapping
|
||||||
|
attrs['_enum_member_map_'] = member_mapping
|
||||||
|
attrs['_enum_member_names_'] = member_names
|
||||||
|
attrs['_enum_value_cls_'] = value_cls
|
||||||
|
actual_cls = super().__new__(cls, name, bases, attrs)
|
||||||
|
value_cls._actual_enum_cls_ = actual_cls # type: ignore # Runtime attribute isn't understood
|
||||||
|
return actual_cls
|
||||||
|
|
||||||
|
def __iter__(cls) -> Iterator[Any]:
|
||||||
|
return (cls._enum_member_map_[name] for name in cls._enum_member_names_)
|
||||||
|
|
||||||
|
def __reversed__(cls) -> Iterator[Any]:
|
||||||
|
return (cls._enum_member_map_[name] for name in reversed(cls._enum_member_names_))
|
||||||
|
|
||||||
|
def __len__(cls) -> int:
|
||||||
|
return len(cls._enum_member_names_)
|
||||||
|
|
||||||
|
def __repr__(cls) -> str:
|
||||||
|
return f'<enum {cls.__name__}>'
|
||||||
|
|
||||||
|
@property
|
||||||
|
def __members__(cls) -> Mapping[str, Any]:
|
||||||
|
return types.MappingProxyType(cls._enum_member_map_)
|
||||||
|
|
||||||
|
def __call__(cls, value: str) -> Any:
|
||||||
|
try:
|
||||||
|
return cls._enum_value_map_[value]
|
||||||
|
except (KeyError, TypeError):
|
||||||
|
raise ValueError(f"{value!r} is not a valid {cls.__name__}")
|
||||||
|
|
||||||
|
def __getitem__(cls, key: str) -> Any:
|
||||||
|
return cls._enum_member_map_[key]
|
||||||
|
|
||||||
|
def __setattr__(cls, name: str, value: Any) -> None:
|
||||||
|
raise TypeError('Enums are immutable.')
|
||||||
|
|
||||||
|
def __delattr__(cls, attr: str) -> None:
|
||||||
|
raise TypeError('Enums are immutable')
|
||||||
|
|
||||||
|
def __instancecheck__(self, instance: Any) -> bool:
|
||||||
|
# isinstance(x, Y)
|
||||||
|
# -> __instancecheck__(Y, x)
|
||||||
|
try:
|
||||||
|
return instance._actual_enum_cls_ is self
|
||||||
|
except AttributeError:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from enum import Enum
|
||||||
|
else:
|
||||||
|
class Enum(metaclass=EnumMeta):
|
||||||
|
@classmethod
|
||||||
|
def try_value(cls, value):
|
||||||
|
try:
|
||||||
|
return cls._enum_value_map_[value]
|
||||||
|
except (KeyError, TypeError):
|
||||||
|
return value
|
||||||
|
|
||||||
|
E = TypeVar('E', bound='Enum')
|
||||||
|
|
||||||
|
def create_unknown_value(cls: Type[E], val: Any) -> E:
|
||||||
|
value_cls = cls._enum_value_cls_ # type: ignore # This is narrowed below
|
||||||
|
name = f'unknown_{val}'
|
||||||
|
return value_cls(name=name, value=val)
|
||||||
|
|
||||||
|
|
||||||
|
def try_enum(cls: Type[E], val: Any) -> E:
|
||||||
|
"""A function that tries to turn the value into enum ``cls``.
|
||||||
|
If it fails it returns a proxy invalid value instead.
|
||||||
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
return cls._enum_value_map_[val] # type: ignore # All errors are caught below
|
||||||
|
except (KeyError, TypeError, AttributeError):
|
||||||
|
return create_unknown_value(cls, val)
|
||||||
|
|
||||||
|
|
||||||
|
# The line above is based on the code in the following url
|
||||||
|
# https://github.com/Rapptz/discord.py/blob/f7e97954950ffb0e34238d70813454caa6f1a3ae/discord/enums.py
|
||||||
|
|
||||||
|
|
||||||
|
# class EyeId(Enum):
|
||||||
|
# # https://docs.python.org/3.9/library/enum.html#functional-api
|
||||||
|
# # > The reason for defaulting to 1 as the starting number and not 0 is that 0 is False in a boolean sense, but enum members all evaluate to True.
|
||||||
|
# RIGHT = 1
|
||||||
|
# LEFT = 2
|
||||||
|
# BOTH = 3
|
||||||
|
# SETTINGS = 4
|
||||||
|
#
|
||||||
|
# def __str__(self) -> str:
|
||||||
|
# return self.name
|
||||||
|
#
|
||||||
|
# def __int__(self) -> int:
|
||||||
|
# return self.value
|
||||||
|
|
||||||
|
class EyeLR(Enum):
|
||||||
|
LEFT = 1
|
||||||
|
RIGHT = 2
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
def __int__(self) -> int:
|
||||||
|
return self.value
|
||||||
@ -48,6 +48,7 @@ from enum import Enum
|
|||||||
from one_euro_filter import OneEuroFilter
|
from one_euro_filter import OneEuroFilter
|
||||||
from utils.misc_utils import PlaySound, SND_FILENAME, SND_ASYNC
|
from utils.misc_utils import PlaySound, SND_FILENAME, SND_ASYNC
|
||||||
import importlib
|
import importlib
|
||||||
|
from osc import EyeId
|
||||||
from osc_calibrate_filter import *
|
from osc_calibrate_filter import *
|
||||||
from haar_surround_feature import External_Run_HSF
|
from haar_surround_feature import External_Run_HSF
|
||||||
from blob import *
|
from blob import *
|
||||||
@ -150,6 +151,9 @@ class EyeProcessor:
|
|||||||
self.er_hsf = None
|
self.er_hsf = None
|
||||||
self.er_hsrac = None
|
self.er_hsrac = None
|
||||||
|
|
||||||
|
self.ibo = IntensityBasedOpeness(eyeside=EyeLR.LEFT if self.eye_id is EyeId.LEFT else EyeLR.RIGHT if eye_id is EyeId.RIGHT else -1)
|
||||||
|
self.roi_include_set = {"rotation_angle", "roi_window_x", "roi_window_y"}
|
||||||
|
|
||||||
self.failed = 0
|
self.failed = 0
|
||||||
|
|
||||||
self.skip_blink_detect = False
|
self.skip_blink_detect = False
|
||||||
@ -209,6 +213,7 @@ class EyeProcessor:
|
|||||||
self.config.roi_window_x + self.config.roi_window_w
|
self.config.roi_window_x + self.config.roi_window_w
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
self.ibo.change_roi(self.config.dict(include=self.roi_include_set))
|
||||||
|
|
||||||
except:
|
except:
|
||||||
# Failure to process frame, reuse previous frame.
|
# Failure to process frame, reuse previous frame.
|
||||||
@ -253,7 +258,8 @@ class EyeProcessor:
|
|||||||
# if (cx - self.prev_x) <= 45 and (cy - self.prev_y) <= 45 :
|
# if (cx - self.prev_x) <= 45 and (cy - self.prev_y) <= 45 :
|
||||||
# self.prev_x = cx
|
# self.prev_x = cx
|
||||||
# self.prev_y = cy
|
# self.prev_y = cy
|
||||||
self.eyeopen = intense(cx, cy, uncropframe, self.eye_id)
|
# self.eyeopen = intense(cx, cy, uncropframe, self.eye_id)
|
||||||
|
self.eyeopen = self.ibo.intense(cx,cy,uncropframe)
|
||||||
out_x, out_y = cal_osc(self, cx, cy)
|
out_x, out_y = cal_osc(self, cx, cy)
|
||||||
#print(self.eyeoffx, self.eyeopen)
|
#print(self.eyeoffx, self.eyeopen)
|
||||||
|
|
||||||
@ -267,7 +273,7 @@ class EyeProcessor:
|
|||||||
def HSFM(self):
|
def HSFM(self):
|
||||||
# todo: added process to initialise er_hsf when resolution changes
|
# todo: added process to initialise er_hsf when resolution changes
|
||||||
cx, cy, frame = self.er_hsf.run(self.current_image_gray)
|
cx, cy, frame = self.er_hsf.run(self.current_image_gray)
|
||||||
self.eyeopen = intense(cx, cy, self.current_image_gray)
|
self.eyeopen = self.ibo.intense(cx, cy, self.current_image_gray)
|
||||||
out_x, out_y = cal_osc(self, cx, cy)
|
out_x, out_y = cal_osc(self, cx, cy)
|
||||||
if cx == 0:
|
if cx == 0:
|
||||||
self.output_images_and_update(frame, EyeInformation(InformationOrigin.HSF, out_x, out_y, 0, self.eyeopen)) #update app
|
self.output_images_and_update(frame, EyeInformation(InformationOrigin.HSF, out_x, out_y, 0, self.eyeopen)) #update app
|
||||||
@ -276,7 +282,7 @@ class EyeProcessor:
|
|||||||
|
|
||||||
def RANSAC3DM(self):
|
def RANSAC3DM(self):
|
||||||
cx, cy, thresh = RANSAC3D(self)
|
cx, cy, thresh = RANSAC3D(self)
|
||||||
self.eyeopen = intense(cx, cy, self.current_image_gray)
|
self.eyeopen = self.ibo.intense(cx, cy, self.current_image_gray)
|
||||||
out_x, out_y = cal_osc(self, cx, cy)
|
out_x, out_y = cal_osc(self, cx, cy)
|
||||||
if cx == 0:
|
if cx == 0:
|
||||||
self.output_images_and_update(thresh, EyeInformation(InformationOrigin.RANSAC, out_x, out_y, 0, self.eyeopen)) #update app
|
self.output_images_and_update(thresh, EyeInformation(InformationOrigin.RANSAC, out_x, out_y, 0, self.eyeopen)) #update app
|
||||||
@ -285,7 +291,7 @@ class EyeProcessor:
|
|||||||
|
|
||||||
def BLOBM(self):
|
def BLOBM(self):
|
||||||
cx, cy, thresh = BLOB(self)
|
cx, cy, thresh = BLOB(self)
|
||||||
self.eyeopen = intense(cx, cy, self.current_image_gray)
|
self.eyeopen = self.ibo.intense(cx, cy, self.current_image_gray)
|
||||||
out_x, out_y = cal_osc(self, cx, cy)
|
out_x, out_y = cal_osc(self, cx, cy)
|
||||||
if cx == 0:
|
if cx == 0:
|
||||||
self.output_images_and_update(thresh, EyeInformation(InformationOrigin.HSRAC, out_x, out_y, 0, self.eyeopen)) #update app
|
self.output_images_and_update(thresh, EyeInformation(InformationOrigin.HSRAC, out_x, out_y, 0, self.eyeopen)) #update app
|
||||||
|
|||||||
@ -2,17 +2,11 @@ import numpy as np
|
|||||||
import time
|
import time
|
||||||
import os
|
import os
|
||||||
import cv2
|
import cv2
|
||||||
from enum import IntEnum
|
from enums import EyeLR
|
||||||
from osc import EyeId
|
|
||||||
#higher intensity means more closed/ more white/less pupil
|
#higher intensity means more closed/ more white/less pupil
|
||||||
|
|
||||||
#Hm I need an acronym for this, any ideas?
|
#Hm I need an acronym for this, any ideas?
|
||||||
#IBO Intensity Based Openess
|
#IBO Intensity Based Openess
|
||||||
class EyeId(IntEnum):
|
|
||||||
RIGHT = 0
|
|
||||||
LEFT = 1
|
|
||||||
BOTH = 2
|
|
||||||
SETTINGS = 3
|
|
||||||
|
|
||||||
# HOW THIS WORKS:
|
# HOW THIS WORKS:
|
||||||
# we get the intensity of pupil area from HSF crop, When the eyelid starts to close, the pupil starts being obstructed by skin which is generally lighter than the pupil.
|
# we get the intensity of pupil area from HSF crop, When the eyelid starts to close, the pupil starts being obstructed by skin which is generally lighter than the pupil.
|
||||||
@ -26,12 +20,6 @@ class EyeId(IntEnum):
|
|||||||
# https://stackoverflow.com/questions/43185605/how-do-i-read-an-image-from-a-path-with-unicode-characters
|
# https://stackoverflow.com/questions/43185605/how-do-i-read-an-image-from-a-path-with-unicode-characters
|
||||||
# https://github.com/opencv/opencv/issues/18305
|
# https://github.com/opencv/opencv/issues/18305
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
lct = time.time()
|
|
||||||
data = None
|
|
||||||
|
|
||||||
|
|
||||||
def csv2data(frameshape, filepath):
|
def csv2data(frameshape, filepath):
|
||||||
# For data checking
|
# For data checking
|
||||||
frameshape = (frameshape[0], frameshape[1]+1)
|
frameshape = (frameshape[0], frameshape[1]+1)
|
||||||
@ -50,6 +38,7 @@ def csv2data(frameshape, filepath):
|
|||||||
out[xy_list[:, 1], xy_list[:, 0]] = val_list[:]
|
out[xy_list[:, 1], xy_list[:, 0]] = val_list[:]
|
||||||
return out
|
return out
|
||||||
|
|
||||||
|
|
||||||
def data2csv(data_u32, filepath):
|
def data2csv(data_u32, filepath):
|
||||||
# For data checking
|
# For data checking
|
||||||
nonzero_index = np.nonzero(data_u32) #(row,col)
|
nonzero_index = np.nonzero(data_u32) #(row,col)
|
||||||
@ -84,48 +73,76 @@ def newdata(frameshape):
|
|||||||
return np.zeros(frameshape, dtype=np.uint32)
|
return np.zeros(frameshape, dtype=np.uint32)
|
||||||
|
|
||||||
|
|
||||||
def check_and_load(frameshape, now_data, fname):
|
class IntensityBasedOpeness:
|
||||||
|
def __init__(self, eyeside: EyeLR):
|
||||||
|
# todo: It is necessary to consider whether the filename can be changed in the configuration file, etc.
|
||||||
|
self.imgfile = "IBO_LEFT.png" if eyeside is EyeLR.LEFT else "IBO_RIGHT.png"
|
||||||
|
# self.data[0, -1] = maxval, [1, -1] = rotation, [2, -1] = x, [3, -1] = y
|
||||||
|
self.data = None
|
||||||
|
self.lct = None
|
||||||
|
self.maxval = 0
|
||||||
|
# self.img_roi = self.now_roi == {"rotation": 0, "x": 0, "y": 0}
|
||||||
|
self.img_roi = np.zeros(3, dtype=np.int32)
|
||||||
|
self.now_roi = np.zeros(3, dtype=np.int32)
|
||||||
|
|
||||||
|
def check(self, frameshape):
|
||||||
|
# 0 in data is used as the initial value.
|
||||||
|
# When assigning a value, +1 is added to the value to be assigned.
|
||||||
|
self.load(frameshape)
|
||||||
|
# self.maxval = self.data[0, -1]
|
||||||
|
if self.lct is None:
|
||||||
|
self.lct = time.time()
|
||||||
|
|
||||||
|
def load(self, frameshape):
|
||||||
req_newdata = False
|
req_newdata = False
|
||||||
# Not very clever, but increase the width by 1px to save the maximum value.
|
# Not very clever, but increase the width by 1px to save the maximum value.
|
||||||
frameshape = (frameshape[0], frameshape[1] + 1)
|
frameshape = (frameshape[0], frameshape[1] + 1)
|
||||||
if now_data is None:
|
if self.data is None:
|
||||||
print("Load data for blinking: {}".format(fname))
|
print("Load data for blinking: {}".format(self.imgfile))
|
||||||
if os.path.isfile(fname):
|
if os.path.isfile(self.imgfile):
|
||||||
img = cv2.imread(fname, flags=cv2.IMREAD_UNCHANGED)
|
try:
|
||||||
|
img = cv2.imread(self.imgfile, flags=cv2.IMREAD_UNCHANGED)
|
||||||
if img.shape[:2] != frameshape:
|
if img.shape[:2] != frameshape:
|
||||||
print("size does not match the input frame.")
|
print("size does not match the input frame.")
|
||||||
req_newdata = True
|
req_newdata = True
|
||||||
else:
|
else:
|
||||||
now_data = u16_u32_3ch_1ch(img)
|
self.data = u16_u32_3ch_1ch(img)
|
||||||
|
self.img_roi[:] = self.data[1:4, -1]
|
||||||
|
if not np.array_equal(self.img_roi, self.now_roi):
|
||||||
|
# If the ROI recorded in the image file differs from the current ROI
|
||||||
|
req_newdata = True
|
||||||
|
else:
|
||||||
|
self.maxval = self.data[0, -1]
|
||||||
|
except:
|
||||||
|
print("File read error: {}".format(self.imgfile))
|
||||||
|
req_newdata = True
|
||||||
else:
|
else:
|
||||||
print("File does not exist.")
|
print("File does not exist.")
|
||||||
req_newdata = True
|
req_newdata = True
|
||||||
else:
|
else:
|
||||||
if now_data.shape != frameshape:
|
if self.data.shape != frameshape or not np.array_equal(self.img_roi, self.now_roi):
|
||||||
# Using the previous and current frame sizes and centre positions from the original, etc., the data can be ported to some extent, but there may be many areas where code changes are required.
|
# If the ROI recorded in the image file differs from the current ROI
|
||||||
|
#todo: Using the previous and current frame sizes and centre positions from the original, etc., the data can be ported to some extent, but there may be many areas where code changes are required.
|
||||||
print("Frame size changed.")
|
print("Frame size changed.")
|
||||||
req_newdata = True
|
req_newdata = True
|
||||||
if req_newdata:
|
if req_newdata:
|
||||||
now_data = newdata(frameshape)
|
self.data = newdata(frameshape)
|
||||||
|
self.maxval = 0
|
||||||
# data2csv(now_data, "a.csv")
|
self.img_roi = self.now_roi.copy()
|
||||||
|
# data2csv(self.data, "a.csv")
|
||||||
# csv2data(frameshape,"a.csv")
|
# csv2data(frameshape,"a.csv")
|
||||||
return now_data
|
|
||||||
|
|
||||||
|
def save(self):
|
||||||
|
self.data[0, -1] = self.maxval
|
||||||
|
self.data[1:4, -1] = self.now_roi
|
||||||
|
cv2.imwrite(self.imgfile, u32_u16_1ch3ch(self.data))
|
||||||
|
print("SAVED: {}".format(self.imgfile))
|
||||||
|
|
||||||
def intense(x, y, frame, eye_id):
|
def change_roi(self, roiinfo: dict):
|
||||||
global lct, data
|
self.now_roi[:] = [v for v in roiinfo.values()]
|
||||||
e = False
|
|
||||||
if eye_id in [EyeId.RIGHT]: #TODO run only once
|
|
||||||
fname = "IBO_RIGHT.png"
|
|
||||||
eye = "RIGHT"
|
|
||||||
if eye_id in [EyeId.LEFT]:
|
|
||||||
fname = "IBO_LEFT.png"
|
|
||||||
eye = "LEFT"
|
|
||||||
|
|
||||||
# 0 in data is used as the initial value.
|
def intense(self, x, y, frame):
|
||||||
# When assigning a value, +1 is added to the value to be assigned.
|
self.check(frame.shape)
|
||||||
data = check_and_load(frame.shape[:2], data, fname)
|
|
||||||
int_x, int_y = int(x), int(y)
|
int_x, int_y = int(x), int(y)
|
||||||
|
|
||||||
# upper_x = min(int_x + 25, frame.shape[1]) #TODO make this a setting
|
# upper_x = min(int_x + 25, frame.shape[1]) #TODO make this a setting
|
||||||
@ -147,56 +164,50 @@ def intense(x, y, frame, eye_id):
|
|||||||
if int_y >= frame.shape[0]:
|
if int_y >= frame.shape[0]:
|
||||||
# data_val = 1
|
# data_val = 1
|
||||||
int_y = frame.shape[0] - 1
|
int_y = frame.shape[0] - 1
|
||||||
e = True
|
|
||||||
print('CAUGHT Y OUT OF BOUNDS')
|
print('CAUGHT Y OUT OF BOUNDS')
|
||||||
|
|
||||||
if int_x >= frame.shape[1]:
|
if int_x >= frame.shape[1]:
|
||||||
# data_val = 1
|
# data_val = 1
|
||||||
e = True
|
|
||||||
int_x = frame.shape[0] - 1
|
int_x = frame.shape[0] - 1
|
||||||
print('CAUGHT X OUT OF BOUNDS')
|
print('CAUGHT X OUT OF BOUNDS')
|
||||||
|
|
||||||
#if e == False: #TODO clean this up
|
data_val = self.data[int_y, int_x]
|
||||||
|
|
||||||
data_val = data[int_y, int_x]
|
|
||||||
|
|
||||||
|
|
||||||
# max pupil per cord
|
# max pupil per cord
|
||||||
if data_val == 0:
|
if data_val == 0:
|
||||||
# The value of the specified coordinates has not yet been recorded.
|
# The value of the specified coordinates has not yet been recorded.
|
||||||
data[int_y, int_x] = intensity
|
self.data[int_y, int_x] = intensity
|
||||||
changed = True
|
changed = True
|
||||||
newval_flg = True
|
newval_flg = True
|
||||||
elif intensity < data_val: # if current intensity value is less (more pupil), save that
|
else:
|
||||||
data[int_y, int_x] = intensity # set value
|
if intensity < data_val: # if current intensity value is less (more pupil), save that
|
||||||
|
self.data[int_y, int_x] = intensity # set value
|
||||||
changed = True
|
changed = True
|
||||||
print("var adjusted")
|
print("var adjusted")
|
||||||
else:
|
else:
|
||||||
intensitya = max(data_val - 3, 1) # if current intensity value is less (more pupil), save that
|
intensitya = max(data_val - 3, 1) # if current intensity value is less (more pupil), save that
|
||||||
data[int_y, int_x] = intensitya # set value
|
self.data[int_y, int_x] = intensitya # set value
|
||||||
changed = True
|
changed = True
|
||||||
|
|
||||||
# min pupil global
|
# min pupil global
|
||||||
if data[0, -1] == 0: # that value is not yet saved
|
if self.maxval == 0: # that value is not yet saved
|
||||||
data[0, -1] = intensity # set value at 0 index
|
self.maxval = intensity # set value at 0 index
|
||||||
changed = True
|
|
||||||
print("create max", intensity)
|
print("create max", intensity)
|
||||||
elif intensity > data[0, -1]: # if current intensity value is more (less pupil), save that NOTE: we have the
|
else:
|
||||||
data[0, -1] = intensity # set value at 0 index
|
if intensity > self.maxval: # if current intensity value is more (less pupil), save that NOTE: we have the
|
||||||
changed = True
|
self.maxval = intensity # set value at 0 index
|
||||||
print("new max", intensity)
|
print("new max", intensity)
|
||||||
else:
|
else:
|
||||||
intensityd = max(data[0, -1] - 10, 1) #continuously adjust closed intensity, will be set when user blink, used to allow eyes to close when lighting changes
|
intensityd = max(self.maxval - 10, 1) # continuously adjust closed intensity, will be set when user blink, used to allow eyes to close when lighting changes
|
||||||
data[0, -1] = intensityd # set value at 0 index
|
self.maxval = intensityd # set value at 0 index
|
||||||
changed = True
|
|
||||||
|
|
||||||
if newval_flg:
|
if newval_flg:
|
||||||
# Do the same thing as in the original version.
|
# Do the same thing as in the original version.
|
||||||
print('[INFO] Something went wrong, assuming blink.')
|
print('[INFO] Something went wrong, assuming blink.')
|
||||||
eyeopen = 0.7
|
eyeopen = 0.7
|
||||||
else:
|
else:
|
||||||
maxp = data[int_y, int_x]
|
maxp = self.data[int_y, int_x]
|
||||||
minp = data[0, -1]
|
minp = self.maxval
|
||||||
diffp = minp - maxp if (minp - maxp) != 0 else 1
|
diffp = minp - maxp if (minp - maxp) != 0 else 1
|
||||||
eyeopen = (intensity - maxp) / diffp
|
eyeopen = (intensity - maxp) / diffp
|
||||||
eyeopen = 1 - eyeopen
|
eyeopen = 1 - eyeopen
|
||||||
@ -204,10 +215,9 @@ def intense(x, y, frame, eye_id):
|
|||||||
# print(intensity, maxp, minp, x, y)
|
# print(intensity, maxp, minp, x, y)
|
||||||
# print(f"EYEOPEN: {eyeopen}")
|
# print(f"EYEOPEN: {eyeopen}")
|
||||||
# print(int(x), int(y), eyeopen, maxp, minp)
|
# print(int(x), int(y), eyeopen, maxp, minp)
|
||||||
print(data[0, -1])
|
# print(self.data[0, -1])
|
||||||
if changed and ((time.time() - lct) > 4): # save every 4 seconds if something changed to save disk usage
|
# print(self.maxval)
|
||||||
cv2.imwrite(fname, u32_u16_1ch3ch(data))
|
if changed and ((time.time() - self.lct) > 4): # save every 4 seconds if something changed to save disk usage
|
||||||
lct = time.time()
|
self.save()
|
||||||
print("SAVED")
|
self.lct = time.time()
|
||||||
|
|
||||||
return eyeopen
|
return eyeopen
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user