Tuesday, February 5, 2008

Day 2 - Plotting the gaze

After successfully hooking up a socket to listen to the UDP stream from the SMI IViewX RED eye tracker the next objective was to draw or plot the gaze on the screen so that I could visually see where I was gazing (!) Or, where the eye tracker would suggest that my gaze was directed.

The UDP stream provided me with the X and Y coordinates of my gaze. Now I needed a Windows program that would enable me to start the client, receive the data and plot this graphically. In order to do this I created a delegate for an event handler. This means that when ever the program received a new gaze position it would fire an event. The main program will in turn register a listener for this event that would call for a function that draws a small box on the screen based on the X and Y coordinates collected.



[EyeTrackerServer.cs]

public delegate void GazeChangedEventHandler(object source, EventArgs e);
public GazeChangedEventHandler onGazeChange;
In addition to this I decided to create an object "GazeData" that would carry a function to extract the X and Y position from the datastream and set this as two integers. These were to be named GazePositionX and GazePositionY.

So, in the main loop of the program where the raw data string was previously just printed to the console I instead passed it on to a function.

[EyeTrackerServer.cs]

datareceived = System.Text.Encoding.ASCII.GetString(received);

if (datareceived.Length > 0)
{
extractGazePosition(datareceived);
}
And then the function itself, after parsing and setting the X and Y the function fires the event "OnGazeChange"

[EyeTrackerServer.cs]
 public void extractGazePosition(string data)
{
GazeData.extractTrackerData(data);

if (onGazeChange != null)
onGazeChange(this, EventArgs.Empty);
}
The GazeData object contains the function for extracting the X and Y and property set/getters
....
   public void extractTrackerData(string dataStr)
{
char[] seperator = { ' ' };
string[] tmp = dataStr.Split(seperator, 10);
this.TimeStamp = Convert.ToInt32(tmp[1]);
this.gazePositionX = Convert.ToInt32(tmp[2]);
this.gazePositionY = Convert.ToInt32(tmp[4]);
}
The main windows application would create a listener for the OnGazeChange event:
[Program.cs]
 myServer.onGazeChange +=
new EyeTrackerServer.GazeChangedEventHandler(onGazeChange);
And when the server would receive a new gaze reading it would signal to the eventHandler to fire this function that draws a rectangle on the screen

[Program.cs]
 public void onGazeChange(object source, EventArgs e)
{
PlotGazePosition(myServer.GazeData.GazePositionX,
myServer.GazeData.GazePositionY);
}

public void PlotGazePosition(int x, int y)
{
Graphics G = this.CreateGraphics();
Pen myPen = new Pen(Color.Red);
Random rnd = new Random((int)DateTime.Now.Ticks);

// Little bit of random colors just for fun...
myPen.Color = Color.FromArgb(
(int)rnd.Next(0, 255),
(int)rnd.Next(0, 255),
(int)rnd.Next(0, 200));

// The shape of the rectangles are slightly random too, just to make it artistic..
G.DrawRectangle(myPen, x, y, (int)rnd.Next(5,25), (int)rnd.Next(5,25));
Happily gazing at my own gaze pattern and trying to draw with it on the screen it was just about time to wrap up day two. So far, so good. However, I did notice that the gaze data was full of jitter. When ever I would fixate on one specific point the plotter would jump around in an area about the size of a.. coca-cola cap. Was this part of the tracker or normal eye behavior. In general, our eyes are never still. When we fixate on objects small eye movements called microsaccades takes place. Supposedly (there is a debate) this is how we are able to keep items in focus. If the eye would be completely fixated the image would slowly fade away (reminds me of some plasma tv screens that do the same so that the image would not "burn" into the panel)

No comments: