private static void AddPoint(EyeTrackerErrorCorrection correction) { lock (Helpers.locker) { points.Insert(0, correction); while (points.Count > Options.Instance.smothening_points_count) { points.RemoveAt(points.Count - 1); } points.RemoveAll(p => { if (p.сoordinates.Length != correction.сoordinates.Length) { return(true); } for (int i = 0; i < p.сoordinates.Length; i++) { if (Math.Abs(p.сoordinates[i] - correction.сoordinates[i]) > Options.Instance.instant_jump_distance) { return(true); } } return(false); }); } }
public void UpdateCurrentCorrection(EyeTrackerErrorCorrection correction) { Dispatcher.BeginInvoke((Action)(() => { color_calculator.AdjustColorBoundaries(correction.сoordinates); InitArrowWithUserCorrection(correction, current_arrow); })); }
private void OnNewCoordinates(TobiiCoordinates coordinates) { lock (Helpers.locker) { if (mouse_state == MouseState.Idle && (DateTime.Now - idle_start_time).TotalSeconds > 60) { CoordinateSmoother.Reset(); return; } if (DateTime.Now > freeze_until) { if (mouse_state == MouseState.Calibrating && Helpers.GetDistance(coordinates.gaze_point, calibration_start_gaze_point) > Options.Instance.reset_calibration_zone_size) { mouse_state = MouseState.Controlling; } if (mouse_state == MouseState.Calibrating) { // The only thing to update while calibrating is gaze point. float[] coordinates_copy = new float[smoothened_error_correction.сoordinates.Length]; smoothened_error_correction.сoordinates.CopyTo(coordinates_copy, 0); var smoothened_error_correction_clone = new EyeTrackerErrorCorrection(coordinates_copy, smoothened_error_correction.shift); smoothened_error_correction_clone.сoordinates[0] = coordinates.gaze_point.X; smoothened_error_correction_clone.сoordinates[1] = coordinates.gaze_point.Y; smoothened_error_correction = CoordinateSmoother.Smoothen(smoothened_error_correction_clone); } else { // The eye tracker provides shaky data that has to be smoothened before transforming to the mouse cursor position. // |CalibrationManager| amplifies this shaking. // To cancel the amplification we smoothen data BEFORE it goes to |CalibrationManager|. // // Another problem is |CalibrationManager| also may be a source of shaking (even on smoothened input). // So in addition to smoothening its input we have to smoothen its output. // Smoothening data twice leads to bigger latency but otherwise, the cursor shakes. // Big latency is compensated by |instant_jump_distance|. var shift = smoothened_error_correction == null ? new Point(0, 0) : CalibrationManager.Instance.GetShift(smoothened_error_correction.сoordinates); var shaky_coordinates = coordinates.ToCoordinates(Options.Instance.calibration_mode.additional_dimensions_configuration); smoothened_error_correction = CoordinateSmoother.Smoothen(new EyeTrackerErrorCorrection(shaky_coordinates, shift)); } } else { // Adds inertia on exit from freeze state. CoordinateSmoother.Smoothen(smoothened_error_correction); } if (mouse_state == MouseState.Controlling || mouse_state == MouseState.Calibrating) { UpdateCursorPosition(); } } }
private void InitArrowWithUserCorrection(EyeTrackerErrorCorrection shift, Petzold.Media2D.ArrowLine arrow) { arrow.X1 = shift.сoordinates[0]; arrow.Y1 = shift.сoordinates[1]; arrow.X2 = shift.сoordinates[0] + shift.shift.X; arrow.Y2 = shift.сoordinates[1] + shift.shift.Y; if (arrow == current_arrow) { arrow.Stroke = Brushes.Green; } else { arrow.Stroke = Options.Instance.calibration_mode.additional_dimensions_configuration.Equals(AdditionalDimensionsConfguration.Disabled) ? Brushes.Red : new SolidColorBrush(color_calculator.GetColor(shift.сoordinates)); } arrow.StrokeThickness = 3; }
public static EyeTrackerErrorCorrection Smoothen(EyeTrackerErrorCorrection correction) { AddPoint(correction); float[] coordinates = new float[correction.сoordinates.Length]; Point shift = new Point(0, 0); foreach (var point in points) { shift.X += point.shift.X; shift.Y += point.shift.Y; for (int i = 0; i < coordinates.Length; i++) { coordinates[i] += point.сoordinates[i]; } } shift.X = shift.X / points.Count; shift.Y = shift.Y / points.Count; for (int i = 0; i < coordinates.Length; i++) { coordinates[i] = coordinates[i] / points.Count; } return(new EyeTrackerErrorCorrection(coordinates, shift)); }