aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/argaze/GazeFeatures.py50
1 files changed, 36 insertions, 14 deletions
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 ?