Fixed smoothing, fixed config_update issues, hid smoothing settings

This commit is contained in:
Blabzillaweasel 2025-02-15 23:25:12 +13:00
parent 79403f365a
commit 28b6c58a49
5 changed files with 116 additions and 75 deletions

View File

@ -221,11 +221,12 @@ class EyeTrackSettingsConfig(BaseModel):
gui_mirrortrack_enabled: bool = False
gui_mirrortrack_select_right: bool = True
gui_mirrortrack_cycle_count_inv: int = 20
gui_mirrortrack_cycle_count_stare: int = 20
#gui_mirrortrack_smoothing_rate: float = 0.025
gui_mirrortrack_cycle_count_stare: int = 10
gui_mirrortrack_smooth_rate: float = 0.2
gui_mirrortrack_minthresh: float = 0.3
gui_mirrortrack_rotation_clamp: float = 0.5
gui_mirrortrack_enable_inv: bool = True
gui_mirrortrack_enable_smooth: bool = True
class EyeTrackConfig(BaseModel):
version: int = 1

View File

@ -38,7 +38,7 @@ from settings.algo_settings_widget import AlgoSettingsWidget
from osc.osc import OSCManager
from osc.OSCMessage import OSCMessage
from utils.misc_utils import is_nt, resource_path
from utils.mirrortrack import mirrortrack
from utils.mirrortrack import MirrorTrack
import cv2
import numpy as np
import uuid
@ -284,7 +284,7 @@ def main():
config.register_listener_callback(osc_manager.update)
config.register_listener_callback(eyes[0].on_config_update)
config.register_listener_callback(eyes[1].on_config_update)
config.register_listener_callback(mirrortrack.config_update)
config.register_listener_callback(MirrorTrack.config_update)
osc_manager.register_listeners(
config.settings.gui_osc_recenter_address,
@ -302,7 +302,7 @@ def main():
)
osc_manager.start()
mirrortrack.init_config(config)
MirrorTrack.init_config(config)
while True:
tint = 33

View File

@ -10,26 +10,28 @@ from settings.modules.CommonFieldValidators import try_convert_to_int
class MirrorTrackValidationModule(BaseValidationModel):
gui_mirrortrack_enabled: bool
gui_mirrortrack_enable_inv: bool
#gui_mirrortrack_enable_smooth: bool
gui_mirrortrack_select_right: bool
gui_mirrortrack_cycle_count_inv: Annotated[int, AfterValidator(try_convert_to_int)]
gui_mirrortrack_cycle_count_stare: Annotated[int, AfterValidator(try_convert_to_int)]
gui_mirrortrack_minthresh: Annotated[float, AfterValidator(try_convert_to_float)]
gui_mirrortrack_rotation_clamp: Annotated[float, AfterValidator(try_convert_to_float)]
gui_mirrortrack_enable_inv: bool
#gui_mirrortrack_smoothing_rate: Annotated[float, AfterValidator(try_convert_to_float)]
gui_mirrortrack_smooth_rate: Annotated[float, AfterValidator(try_convert_to_float)]
class MirrorTrackSettingsModule(BaseSettingsModule):
def __init__(self, config, widget_id, **kwargs):
super().__init__(config=config, widget_id=widget_id, **kwargs)
self.validation_model = MirrorTrackValidationModule
self.gui_mirrortrack_enabled = f"-gui_mirrortrack_enabled{widget_id}-"
self.gui_mirrortrack_enable_inv =f"-gui_mirrortrack_enable_inv{widget_id}-"
#self.gui_mirrortrack_enable_smooth =f"-gui_mirrortrack_enable_smooth{widget_id}-"
self.gui_mirrortrack_select_right = f"-gui_mirrortrack_select_right{widget_id}-"
self.gui_mirrortrack_cycle_count_inv =f"-gui_mirrortrack_cycle_count_inv{widget_id}-"
self.gui_mirrortrack_cycle_count_stare =f"-gui_mirrortrack_cycle_count_stare{widget_id}-"
self.gui_mirrortrack_minthresh =f"-gui_mirrortrack_minthresh{widget_id}-"
self.gui_mirrortrack_rotation_clamp =f"-gui_mirrortrack_rotation_clamp{widget_id}-"
self.gui_mirrortrack_enable_inv =f"-gui_mirrortrack_enable_inv{widget_id}-"
#self.gui_mirrortrack_smoothing_rate =f"-gui_mirrortrack_smoothing_rate{widget_id}-"
self.gui_mirrortrack_smooth_rate =f"-gui_mirrortrack_smooth_rate{widget_id}-"
def get_layout(self):
return [
@ -38,7 +40,7 @@ class MirrorTrackSettingsModule(BaseSettingsModule):
],
[
sg.Checkbox(
"Enable:",
"Enable MirrorTrack",
default=self.config.gui_mirrortrack_enabled,
key=self.gui_mirrortrack_enabled,
background_color="#424042",
@ -74,7 +76,7 @@ class MirrorTrackSettingsModule(BaseSettingsModule):
),
],
[
sg.Text("Transition Cycle Count (Cross Eye)", background_color=BACKGROUND_COLOR,tooltip=
sg.Text("Transition Cycle Count (Cross-Eye)", background_color=BACKGROUND_COLOR,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."
),
@ -95,28 +97,14 @@ class MirrorTrackSettingsModule(BaseSettingsModule):
size=(0, 10),
),
],
#[
# sg.Text("Smoothing Decay Rate", background_color=BACKGROUND_COLOR,tooltip=
# "How quickly eye smoothing decays when you enter or leave a cross-eyed state."
# "\nHigher number = shorter smoothing duration."
# ),
# sg.InputText(
# self.config.gui_mirrortrack_smoothing_rate,
# key=self.gui_mirrortrack_smoothing_rate,
# size=(0, 10),
# ),
#],
[
sg.Checkbox(
"Allow cross-eye:",
"Allow cross-eye",
default=self.config.gui_mirrortrack_enable_inv,
key=self.gui_mirrortrack_enable_inv,
background_color="#424042",
tooltip="Enables cross-eye functionality",
),
],
[
sg.Text("Maximum allowed cross-eye", background_color=BACKGROUND_COLOR,tooltip=
"Defines the maximum inwards rotation that is output when cross-eyed."
"\n0 = will only look straight ahead \n0.5 = will go a little bit cross-eyed \n1 = maximum hurr durr "
@ -127,5 +115,24 @@ class MirrorTrackSettingsModule(BaseSettingsModule):
size=(0, 10),
),
],
[
#sg.Checkbox(
# "Allow cross-eye smoothing",
# default=self.config.gui_mirrortrack_enable_smooth,
# key=self.gui_mirrortrack_enable_smooth,
# background_color="#424042",
# tooltip="Enables smoothing when transitioning to cross-eye",
#),
sg.Text("Smoothing Rate", background_color=BACKGROUND_COLOR,tooltip=
"How quickly smoothing decays when you enter or leave a transition."
"\nHigher number = shorter smoothing duration, snappier transition."
"\nLower number = longer smoothing duration, smoother transition"
),
sg.InputText(
self.config.gui_mirrortrack_smooth_rate,
key=self.gui_mirrortrack_smooth_rate,
size=(0, 10),
),
],
]

View File

@ -25,7 +25,6 @@ class MirrorTrack:
#Defines our processed positions
tx_left_x = 0.0
tx_left_y = 0.0
tx_right_x = 0.0
tx_right_y = 0.0
tx_dom_eye_x = 0.0
@ -35,6 +34,7 @@ class MirrorTrack:
inv_x_thresh = 0.3
is_r_dom = True
bypass_stare = False
smoothing_trigger = False
#Defines variables that require settings
@classmethod
@ -49,7 +49,7 @@ class MirrorTrack:
cls.is_r_dom = False
#Inversion related
cls.inv_is_enabled = config.settings.gui_mirrortrack_enable_inv
cls.is_inv_enabled = config.settings.gui_mirrortrack_enable_inv
cls.inv_x_thresh = config.settings.gui_mirrortrack_minthresh
cls.inv_clamp = config.settings.gui_mirrortrack_rotation_clamp
@ -59,7 +59,8 @@ class MirrorTrack:
cls.cyc_counter_inv = CycleCounter(cls.cyc_counts_inv)
cls.cyc_counter_stare = CycleCounter(cls.cyc_counts_stare)
cls.smoothing_rate = config.settings.gui_mirrortrack_
cls.is_smooth_enabled = config.settings.gui_mirrortrack_enable_smooth
cls.smoothing_rate = config.settings.gui_mirrortrack_smooth_rate
cls.thread_lock = threading.Lock()
@ -78,13 +79,13 @@ class MirrorTrack:
print(f"MirrorTrack transition threshold changed to {cls.inv_x_thresh}")
if "gui_mirrortrack_cycle_count_inv" in data:
cls.cyc_counts_stare = data["gui_mirrortrack_cycle_count_inv"]
cls.cyc_counter_stare.update(cls.cyc_counts_stare)
cls.cyc_counts_inv = data["gui_mirrortrack_cycle_count_inv"]
cls.cyc_counter_inv.update(cls.cyc_counts_inv)
print(f"MirrorTrack inversion transition condition required cycle count changed to {cls.cyc_counts_inv}")
if "gui_mirrortrack_cycle_count_stare" in data:
cls.cyc_counts_inv = data["gui_mirrortrack_cycle_count_stare"]
cls.cyc_counter_stare.update(cls.cyc_counts_inv)
cls.cyc_counts_stare = data["gui_mirrortrack_cycle_count_stare"]
cls.cyc_counter_stare.update(cls.cyc_counts_stare)
print(f"MirrorTrack stare transition condition required cycle count changed to {cls.cyc_counts_stare}")
if "gui_mirrortrack_rotation_clamp" in data:
@ -92,8 +93,22 @@ class MirrorTrack:
print(f"MirrorTrack maximum allowed cross-eye changed to {cls.inv_clamp}")
if "gui_mirrortrack_enable_inv" in data:
cls.inv_is_enabled = data["gui_mirrortrack_enable_inv"]
print(f"MirrorTrack allow cross-eye is set to {cls.inv_is_enabled}")
cls.is_inv_enabled = data["gui_mirrortrack_enable_inv"]
if not cls.is_inv_enabled and cls.is_inverted_mode():
cls.set_state("STARE")
cls.bypass_stare = False
print(f"MirrorTrack allow cross-eye is set to {cls.is_inv_enabled}")
if "gui_mirrortrack_enable_smooth" in data:
cls.is_smooth_enabled = data["gui_mirrortrack_enable_smooth"]
print(f"MirrorTrack cross-eye smoothing is set to {cls.is_smooth_enabled}")
if "gui_mirrortrack_smooth_rate" in data:
cls.smoothing_rate = data["gui_mirrortrack_smooth_rate"]
print(f"MirrorTrack cross-eye smoothing rate is set to {cls.smoothing_rate}")
#Main processing function
@classmethod
@ -101,11 +116,12 @@ class MirrorTrack:
with cls.thread_lock:
cls.store_tracked_positions(eye_id,out_x,out_y)
cls.check_for_stare()
if cls.inv_is_enabled:
cls.check_for_inversion()
out_x, out_y = cls.update_new_position(eye_id,out_x,out_y)
out_x = cls.process_smoothing(eye_id,out_x)
cls.store_processed_positions(eye_id,out_x,out_y)
return out_x, out_y
@ -141,9 +157,13 @@ class MirrorTrack:
cls.tx_dom_eye_y = cls.tx_left_y
@classmethod
def check_for_stare(cls):
def check_for_stare(cls,inv_call=False):
if cls.dom_is_inward() and cls.rec_is_inward():
#If inversion exits to stare, force complete the counter to force stare mode.
if inv_call:
cls.cyc_counter_stare.force_complete()
#Updates the counter for stare activation
if not cls.is_stare_mode() and not cls.cyc_counter_stare.is_complete():
cls.cyc_counter_stare.increase()
@ -152,6 +172,10 @@ class MirrorTrack:
elif not cls.is_stare_mode() and cls.cyc_counter_stare.is_complete() and not cls.bypass_stare:
cls.set_state("STARE")
#If inversion exits and doesn't meet stare, reset stare counter to force tracking.
elif inv_call:
cls.cyc_counter_stare.reset()
elif cls.cyc_counter_stare.active():
cls.cyc_counter_stare.decrease()
@ -163,6 +187,7 @@ class MirrorTrack:
@classmethod
def check_for_inversion(cls):
if cls.is_inv_enabled:
if cls.dom_is_inward() and cls.rec_meets_thresh() and (cls.is_stare_mode() or cls.bypass_stare):
#Updates the counter for activation
@ -174,6 +199,7 @@ class MirrorTrack:
elif not cls.is_inverted_mode() and cls.cyc_counter_inv.is_complete():
cls.set_state("INVERTED")
cls.bypass_stare = True
cls.smoothing_trigger = True
#Begins the counter for deactivation if conditions are not met
elif cls.cyc_counter_inv.active():
@ -182,8 +208,11 @@ class MirrorTrack:
if not cls.cyc_counter_inv.active():
if cls.bypass_stare:
cls.bypass_stare = False
cls.cyc_counter_stare.force_complete()
cls.check_for_stare()
if cls.is_inverted_mode():
cls.smoothing_trigger = True
cls.check_for_stare(True)
else:
return
@classmethod
def update_new_position(cls,eye_id,out_x,out_y):
@ -202,9 +231,21 @@ class MirrorTrack:
else:
out_x = clamp(out_x,0,cls.inv_clamp)
return out_x, out_y
@classmethod
def process_smoothing(cls,eye_id,out_x):
if cls.is_smooth_enabled and cls.smoothing_trigger:
smoothing_out_x = cls.tx_right_x if cls.is_processing_right_eye(eye_id) else cls.tx_left_x
smoothing_out_x += (out_x - smoothing_out_x) * cls.smoothing_rate
if abs(out_x - smoothing_out_x) < 0.1:
cls.smoothing_trigger = False
return smoothing_out_x
return out_x
#Helper Methods
@classmethod
def is_tracking_mode(cls):
@ -218,7 +259,7 @@ class MirrorTrack:
@classmethod
def set_state(cls,new_state: str):
cls.state = cls.States[new_state]
print(f"State set to {cls.state.name}")
#print(f"State set to {cls.state.name}")
@classmethod
def is_dominant_eye(cls,eye_id):
return eye_id == cls.dom_eye
@ -240,12 +281,3 @@ class MirrorTrack:
@classmethod
def x_diff(cls):
return abs(cls.rx_left_x - cls.rx_right_x)
@classmethod
def process_smoothing(cls,eye_id,out_x):
if cls.is_processing_right_eye(eye_id):
cls.tx_right_x += (out_x - cls.tx_right_x) * cls.smoothing_rate
out_x = cls.tx_right_x
else:
cls.tx_left_x += (out_x - cls.tx_left_x) * cls.smoothing_rate
out_x = cls.tx_left_x

View File

@ -77,13 +77,14 @@ def eyetrack_settings_config():
#MirrorTrack
gui_mirrortrack_enabled=False,
gui_mirrortrack_enable_inv=False
gui_mirrortrack_enable_smooth=True
gui_mirrortrack_select_right=True,
gui_mirrortrack_cycle_count_inv=20,
gui_mirrortrack_cycle_count_stare=20,
#gui_mirrortrack_smoothing_rate=0.025,
gui_mirrortrack_smooth_rate=0.2,
gui_mirrortrack_minthresh=0.3,
gui_mirrortrack_rotation_clamp=0.3,
gui_mirrortrack_enable_inv=False
gui_mirrortrack_rotation_clamp=0.5,
)