From fb1a05aa8c309263d22cbb79e47c8c6f38366790 Mon Sep 17 00:00:00 2001 From: Théo de la Hogue Date: Wed, 21 Sep 2022 18:33:16 +0200 Subject: Checking GazePosition validity. --- src/argaze/GazeFeatures.py | 50 +++++++++++++++++++++++++++++++++------------- 1 file changed, 36 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/argaze/GazeFeatures.py b/src/argaze/GazeFeatures.py index 1c5f537..be5c430 100644 --- a/src/argaze/GazeFeatures.py +++ b/src/argaze/GazeFeatures.py @@ -34,21 +34,26 @@ class GazePosition(): def __array__(self): return numpy.array(self.value) + def valid(self): + return self.accuracy >= 0 + def draw(self, frame, color=(0, 255, 255)): - # Draw point at position - cv.circle(frame, self.value, 2, color, -1) + if self.valid(): + + # Draw point at position + cv.circle(frame, self.value, 2, color, -1) - # Draw accuracy circle - if self.accuracy > 0: - cv.circle(frame, self.value, round(self.accuracy), color, 1) + # Draw accuracy circle + if self.accuracy > 0: + cv.circle(frame, self.value, round(self.accuracy), color, 1) -class GazePositionMissing(GazePosition, Exception): - """Exception to raise when gaze position is missing.""" +class UnvalidGazePosition(GazePosition): + """Unvalid gaze position.""" - def __init__(self, message): + def __init__(self): - super(Exception, self).__init__(message) + super().__init__((math.nan, math.nan), accuracy=-1) class TimeStampedGazePositions(DataStructures.TimeStampedBuffer): """Define timestamped buffer to store gaze positions.""" @@ -126,7 +131,7 @@ class DispersionBasedMovementIdentifier(MovementIdentifier): dispersion: float = field(init=False) euclidian: bool = field(default=True) - centroid: GazePosition = field(init=False) + centroid: tuple = field(init=False) def __post_init__(self): @@ -186,18 +191,30 @@ class DispersionBasedMovementIdentifier(MovementIdentifier): # select timestamped gaze position until a duration threshold (ts_start, gaze_position_start) = remaining_ts_gaze_positions.pop_first() - (ts_current, gaze_position_current) = remaining_ts_gaze_positions.pop_first() + + # Invalid start position + if not gaze_position_start.valid(): + + self.__ts_gaze_positions.pop_first() + continue ts_gaze_positions = TimeStampedGazePositions() ts_gaze_positions[ts_start] = gaze_position_start + (ts_current, gaze_position_current) = remaining_ts_gaze_positions.pop_first() + while (ts_current - ts_start) < self.__duration_threshold: - ts_gaze_positions[ts_current] = gaze_position_current + # Ignore non valid position + # TODO ? Consider invalid position to not break fixation ? + if gaze_position_current.valid(): - if len(remaining_ts_gaze_positions) > 0: + ts_gaze_positions[ts_current] = gaze_position_current + + try: (ts_current, gaze_position_current) = remaining_ts_gaze_positions.pop_first() - else: + + except: break # is it a new fixation ? @@ -215,6 +232,11 @@ class DispersionBasedMovementIdentifier(MovementIdentifier): # select next gaze position ts_next, position_next = remaining_ts_gaze_positions.pop_first() + + # Invalid next position + if not position_next.valid(): + continue + ts_gaze_positions[ts_next] = position_next # how much gaze is dispersed ? -- cgit v1.1