mirror of
https://github.com/EyeTrackVR/EyeTrackVR.git
synced 2025-11-04 14:39:42 +08:00
Updates to smoothing and UI features
This commit is contained in:
parent
16ad603911
commit
3265eb9079
@ -222,7 +222,7 @@ class EyeTrackSettingsConfig(BaseModel):
|
|||||||
gui_smartinversion_select_right: bool = True
|
gui_smartinversion_select_right: bool = True
|
||||||
gui_smartinversion_thresh: float = 0.25
|
gui_smartinversion_thresh: float = 0.25
|
||||||
gui_smartinversion_frame_count: int = 10
|
gui_smartinversion_frame_count: int = 10
|
||||||
|
gui_smartinversion_smoothing_rate: float = 0.025
|
||||||
|
|
||||||
class EyeTrackConfig(BaseModel):
|
class EyeTrackConfig(BaseModel):
|
||||||
version: int = 1
|
version: int = 1
|
||||||
|
|||||||
@ -8,13 +8,12 @@ import PySimpleGUI as sg
|
|||||||
from settings.modules.CommonFieldValidators import try_convert_to_float
|
from settings.modules.CommonFieldValidators import try_convert_to_float
|
||||||
from settings.modules.CommonFieldValidators import try_convert_to_int
|
from settings.modules.CommonFieldValidators import try_convert_to_int
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class SmartInversionValidationModule(BaseValidationModel):
|
class SmartInversionValidationModule(BaseValidationModel):
|
||||||
gui_smartinversion_enabled: bool
|
gui_smartinversion_enabled: bool
|
||||||
gui_smartinversion_select_right: bool
|
gui_smartinversion_select_right: bool
|
||||||
gui_smartinversion_thresh: Annotated[float, AfterValidator(try_convert_to_float)]
|
gui_smartinversion_thresh: Annotated[float, AfterValidator(try_convert_to_float)]
|
||||||
gui_smartinversion_frame_count: Annotated[int, AfterValidator(try_convert_to_int)]
|
gui_smartinversion_frame_count: Annotated[int, AfterValidator(try_convert_to_int)]
|
||||||
|
gui_smartinversion_smoothing_rate: Annotated[float, AfterValidator(try_convert_to_float)]
|
||||||
|
|
||||||
class SmartInversionSettingsModule(BaseSettingsModule):
|
class SmartInversionSettingsModule(BaseSettingsModule):
|
||||||
def __init__(self, config, widget_id, **kwargs):
|
def __init__(self, config, widget_id, **kwargs):
|
||||||
@ -24,6 +23,7 @@ class SmartInversionSettingsModule(BaseSettingsModule):
|
|||||||
self.gui_smartinversion_select_right = f"-gui_smartinversion_select_right{widget_id}-"
|
self.gui_smartinversion_select_right = f"-gui_smartinversion_select_right{widget_id}-"
|
||||||
self.gui_smartinversion_thresh = f"-gui_smartinversion_thresh{widget_id}-"
|
self.gui_smartinversion_thresh = f"-gui_smartinversion_thresh{widget_id}-"
|
||||||
self.gui_smartinversion_frame_count =f"-gui_smartinversion_frame_count{widget_id}"
|
self.gui_smartinversion_frame_count =f"-gui_smartinversion_frame_count{widget_id}"
|
||||||
|
self.gui_smartinversion_smoothing_rate =f"-gui_smartinversion_smoothing_rate{widget_id}"
|
||||||
|
|
||||||
|
|
||||||
def get_layout(self):
|
def get_layout(self):
|
||||||
@ -62,7 +62,10 @@ class SmartInversionSettingsModule(BaseSettingsModule):
|
|||||||
self.config.gui_smartinversion_thresh,
|
self.config.gui_smartinversion_thresh,
|
||||||
key=self.gui_smartinversion_thresh,
|
key=self.gui_smartinversion_thresh,
|
||||||
size=(0, 10),
|
size=(0, 10),
|
||||||
tooltip="Sets the maximum allowed difference in eye position (x-axis) to determine if the eyes are inverted or not."
|
tooltip=(
|
||||||
|
"Sets the maximum allowed difference in eye position (x-axis) to determine if the eyes are cross-eyed or not."
|
||||||
|
"\n Lower value will make cross-eye detection more sensitive."
|
||||||
|
)
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
@ -71,7 +74,22 @@ class SmartInversionSettingsModule(BaseSettingsModule):
|
|||||||
self.config.gui_smartinversion_frame_count,
|
self.config.gui_smartinversion_frame_count,
|
||||||
key=self.gui_smartinversion_frame_count,
|
key=self.gui_smartinversion_frame_count,
|
||||||
size=(0, 10),
|
size=(0, 10),
|
||||||
tooltip="How many frames the inversion conditions must be true (or no longer true) before the inversion state is toggled on or back off."
|
tooltip=(
|
||||||
|
"How long it takes to detect you are cross-eyed, or no longer cross-eyed."
|
||||||
|
"\n Higher number means longer duration before changing in or out of being cross-eyed state."
|
||||||
|
)
|
||||||
|
),
|
||||||
|
],
|
||||||
|
[
|
||||||
|
sg.Text("Smoothing Decay Rate", background_color=BACKGROUND_COLOR),
|
||||||
|
sg.InputText(
|
||||||
|
self.config.gui_smartinversion_smoothing_rate,
|
||||||
|
key=self.gui_smartinversion_smoothing_rate,
|
||||||
|
size=(0, 10),
|
||||||
|
tooltip=(
|
||||||
|
"How quickly eye smoothing decays when you enter or leave a cross-eyed state."
|
||||||
|
"\nHigher number = shorter smoothing duration."
|
||||||
|
)
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
]
|
]
|
||||||
@ -3,15 +3,19 @@ from utils.misc_utils import clamp
|
|||||||
|
|
||||||
def smart_inversion(self, var, out_x, out_y):
|
def smart_inversion(self, var, out_x, out_y):
|
||||||
|
|
||||||
#Checks to see if the class already has frame counts or inversion attributes
|
#Checks to see if the class already has frame counts, inversion attributes or smoothing attributes
|
||||||
if not hasattr(self, "inverted_frame_count"):
|
if not hasattr(self, "smartinversion_inverted_frame_count"):
|
||||||
self.inverted_frame_count = 0
|
self.smartinversion_inverted_frame_count = 0
|
||||||
|
if not hasattr(self, "smartinversion_normal_frame_count"):
|
||||||
if not hasattr(self, "normal_frame_count"):
|
self.smartinversion_normal_frame_count = 0
|
||||||
self.normal_frame_count = 0
|
if not hasattr(self, "smartinversion_is_inverted"):
|
||||||
|
self.smartinversion_is_inverted = False
|
||||||
if not hasattr(self, "is_inverted"):
|
if not hasattr(self, "smartinversion_smoothing_progress"):
|
||||||
self.is_inverted = False
|
self.smartinversion_smoothing_progress = 0
|
||||||
|
if not hasattr(self, "smartinversion_smoothed_eye_x"):
|
||||||
|
self.smartinversion_smoothed_eye_x = 0.0
|
||||||
|
if not hasattr(self, "smartinversion_previous_inversion_state"):
|
||||||
|
self.smartinversion_previous_inversion_state = False
|
||||||
|
|
||||||
#Updates eye positions with latest
|
#Updates eye positions with latest
|
||||||
if self.eye_id == EyeId.LEFT:
|
if self.eye_id == EyeId.LEFT:
|
||||||
@ -24,48 +28,63 @@ def smart_inversion(self, var, out_x, out_y):
|
|||||||
|
|
||||||
#Checks if eyes are inverted, and then activates inversion if the conditions have been true for a specified number of frames.
|
#Checks if eyes are inverted, and then activates inversion if the conditions have been true for a specified number of frames.
|
||||||
if (var.l_eye_x > 0 and var.r_eye_x < 0) and (abs(var.l_eye_x - var.r_eye_x) > self.settings.gui_smartinversion_thresh):
|
if (var.l_eye_x > 0 and var.r_eye_x < 0) and (abs(var.l_eye_x - var.r_eye_x) > self.settings.gui_smartinversion_thresh):
|
||||||
self.inverted_frame_count = min(self.inverted_frame_count + 1, self.settings.gui_smartinversion_frame_count)
|
self.smartinversion_inverted_frame_count = min(self.smartinversion_inverted_frame_count + 1, self.settings.gui_smartinversion_frame_count)
|
||||||
|
|
||||||
if self.inverted_frame_count == self.settings.gui_smartinversion_frame_count:
|
if self.smartinversion_inverted_frame_count == self.settings.gui_smartinversion_frame_count:
|
||||||
self.is_inverted = True
|
if self.smartinversion_previous_inversion_state != self.smartinversion_is_inverted:
|
||||||
self.normal_frame_count = 0
|
self.smartinversion_normal_frame_count = 0
|
||||||
print(f"Inversion Activated")
|
self.smartinversion_is_inverted = True
|
||||||
|
print(f"Inversion Activated")
|
||||||
|
|
||||||
#Checks if the eyes are no longer inverted, and then clears inversion if the conditions haven't been true for a specified number of frames.
|
#Checks if the eyes are no longer inverted, and then clears inversion if the conditions haven't been true for a specified number of frames.
|
||||||
elif self.is_inverted and (
|
elif self.smartinversion_is_inverted and (
|
||||||
not (var.l_eye_x > 0 and var.r_eye_x < 0) or
|
not (var.l_eye_x > 0 and var.r_eye_x < 0) or
|
||||||
abs(var.l_eye_x - var.r_eye_x) <= self.settings.gui_smartinversion_thresh
|
abs(var.l_eye_x - var.r_eye_x) <= self.settings.gui_smartinversion_thresh
|
||||||
):
|
):
|
||||||
|
|
||||||
self.normal_frame_count = min(self.normal_frame_count + 1, self.settings.gui_smartinversion_frame_count)
|
self.smartinversion_normal_frame_count = min(self.smartinversion_normal_frame_count + 1, self.settings.gui_smartinversion_frame_count)
|
||||||
|
|
||||||
if self.normal_frame_count == self.settings.gui_smartinversion_frame_count:
|
if self.smartinversion_normal_frame_count == self.settings.gui_smartinversion_frame_count:
|
||||||
self.is_inverted = False
|
if self.smartinversion_previous_inversion_state != self.smartinversion_is_inverted:
|
||||||
self.inverted_frame_count = 0
|
self.smartinversion_is_inverted = False
|
||||||
print(f"Inversion Cleared")
|
self.smartinversion_inverted_frame_count = 0
|
||||||
|
print(f"Inversion Cleared")
|
||||||
|
|
||||||
|
#Checks if the inversion state has recently been toggled, and activates smoothing
|
||||||
|
if self.smartinversion_previous_inversion_state != self.smartinversion_is_inverted:
|
||||||
|
self.smartinversion_smoothing_progress = 1
|
||||||
|
self.smartinversion_previous_inversion_state = self.smartinversion_is_inverted
|
||||||
|
|
||||||
#Determines which eye is being tracked based off selection and sets values accordingly
|
#Determines which eye is being tracked based off selection and sets values accordingly
|
||||||
if self.settings.gui_smartinversion_select_right:
|
if self.settings.gui_smartinversion_select_right:
|
||||||
tracked_eye_x = var.r_eye_x
|
tracked_eye_x = var.r_eye_x
|
||||||
tracked_eye_y = var.right_y
|
tracked_eye_y = var.right_y
|
||||||
recessive_eye = EyeId.LEFT
|
recessive_eye = EyeId.LEFT
|
||||||
|
dominant_eye = EyeId.RIGHT
|
||||||
else:
|
else:
|
||||||
tracked_eye_x = var.l_eye_x
|
tracked_eye_x = var.l_eye_x
|
||||||
tracked_eye_y = var.left_y
|
tracked_eye_y = var.left_y
|
||||||
recessive_eye = EyeId.RIGHT
|
recessive_eye = EyeId.RIGHT
|
||||||
|
dominant_eye = EyeId.LEFT
|
||||||
|
|
||||||
out_x = tracked_eye_x
|
out_x = tracked_eye_x
|
||||||
out_y = tracked_eye_y
|
out_y = tracked_eye_y
|
||||||
|
|
||||||
#If eyes are inverted, and eye being processed is recessive, invert x value.
|
#Logic if smoothing is activated
|
||||||
if self.eye_id == recessive_eye:
|
if self.smartinversion_smoothing_progress > 0:
|
||||||
if self.is_inverted:
|
smartinversion_lerp_factor = (1 - self.smartinversion_smoothing_progress)
|
||||||
out_x = -tracked_eye_x
|
|
||||||
|
if self.smartinversion_is_inverted and self.eye_id == recessive_eye:
|
||||||
|
self.smartinversion_smoothed_eye_x += (-tracked_eye_x - self.smartinversion_smoothed_eye_x) * smartinversion_lerp_factor
|
||||||
else:
|
else:
|
||||||
out_x = tracked_eye_x
|
self.smartinversion_smoothed_eye_x += (tracked_eye_x - self.smartinversion_smoothed_eye_x) * smartinversion_lerp_factor
|
||||||
else:
|
|
||||||
out_x = tracked_eye_x
|
self.smartinversion_smoothing_progress = max(self.smartinversion_smoothing_progress - self.settings.gui_smartinversion_smoothing_rate, 0)
|
||||||
|
out_x = self.smartinversion_smoothed_eye_x
|
||||||
|
|
||||||
|
#Logic if inversion is active, but smoothing is not active
|
||||||
|
elif self.smartinversion_is_inverted and self.eye_id == recessive_eye:
|
||||||
|
out_x = -tracked_eye_x
|
||||||
|
|
||||||
out_y = tracked_eye_y
|
out_y = tracked_eye_y
|
||||||
|
|
||||||
|
|||||||
@ -80,6 +80,7 @@ def eyetrack_settings_config():
|
|||||||
gui_smartinversion_select_right=True,
|
gui_smartinversion_select_right=True,
|
||||||
gui_smartinversion_thresh=0.5,
|
gui_smartinversion_thresh=0.5,
|
||||||
gui_smartinversion_frame_count=10,
|
gui_smartinversion_frame_count=10,
|
||||||
|
gui_smartinversion_smoothing_rate=0.025,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user