<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-gb">
<link rel="self" type="application/atom+xml" href="http://theeyetribe.com/forum/feed.php?f=8&amp;t=474" />

<title>The Eye Tribe</title>
<subtitle>Developer Forum</subtitle>
<link href="http://theeyetribe.com/forum/index.php" />
<updated>2015-04-22T12:54:16+02:00</updated>

<author><name><![CDATA[The Eye Tribe]]></name></author>
<id>http://theeyetribe.com/forum/feed.php?f=8&amp;t=474</id>
<entry>
<author><name><![CDATA[k.aizenberg@gmail.com]]></name></author>
<updated>2015-04-22T12:54:16+02:00</updated>
<published>2015-04-22T12:54:16+02:00</published>
<id>http://theeyetribe.com/forum/viewtopic.php?t=474&amp;p=1974#p1974</id>
<link href="http://theeyetribe.com/forum/viewtopic.php?t=474&amp;p=1974#p1974"/>
<title type="html"><![CDATA[Depth movement (head forward and back) compensation]]></title>

<content type="html" xml:base="http://theeyetribe.com/forum/viewtopic.php?t=474&amp;p=1974#p1974"><![CDATA[
<span style="font-weight: bold">Update: below there are lot of text, but depth movement correction works roughly</span><br /><br />hello everyone<br /><br />As we can see, moving the head in depth greatly affects gaze Y estimation (up-down)<br />That is, I believe, because Y difference between Pupil and Glints changes during head movement is Z, and tracker wrongly thinks that I looked up or down<br /><br />Before Martin, Javier and team offer Y-error compensation in gaze estimation algorythm (hope soon), <br />I suggest trying to compensate Y error using measures provided by API currently, I mean <span style="font-weight: bold">pcenter Left </span>and <span style="font-weight: bold">pcenter right</span>.<br /><br />The idea is as follows:<br />- calculate the average distance between pcenter left and pcenter right during calibration<br />- adjust Y gaze coordinate streamed by API after calibration using the formula like<span style="font-weight: bold"> (initial Y provided by API)/(average distance between pupils during calibration)*(observed distance between pupils)</span><br />(the coefficient must be different for different screen areas, some filter should be applied, etc., but simple formula looks enough for rough correction of big error)<br /><br />what do you think? who can try (ny experience in programming is not much better than just copy-paste)? <br /><br />It is much better to include such correction into calibration and estimation process, but i dont know neither C# nor math unfortunately (and the code is not open too)<br />I included such correction previously in open-source ITU gaze tracker code (I did it rather intuitively due to lack of knowledge) and it worked perfectly (in terms of Y-error compensation), but that time it became much harder to finish calibration, I dont know why <img src="http://theeyetribe.com/forum/images/smilies/icon_e_smile.gif" alt=":)" title="Smile" /><br /><br /><br /><span style="font-weight: bold"><span style="text-decoration: underline">update below</span></span><br />The error of head movement is very big, especially for me (due to glasses I have to place tracker closer to face), and both in Y and X (try it at screen corners), though X-error is much smaller<br />I implemented a very rough correction in <span style="font-weight: bold">TETWinSamples code, C#</span><br />Start with Calibration, then press Mouse Control, please find below (i'm not a programmer neither a mathematics-skilled, make it better if possible)<br />The last portion of code is formula that can be applied to coordinates reported by API<br /><br /><span style="color: #FF0000">TETWinSamples code is open-source one, and I hope I did not brake any rules, if yes - I apologies and ask moderator to delete the post</span><br /><br /><br /><span style="font-weight: bold">below the changes that greatly decrease the error for my setup</span> If something does not work, I can send files, but can not help with programming at all <img src="http://theeyetribe.com/forum/images/smilies/icon_e_smile.gif" alt=":)" title="Smile" /><br /><br /><span style="font-weight: bold"><span style="text-decoration: underline">1.</span>Make set of global variables necessary for correction</span> to connect different parts of code together. I inserted the code into <span style="font-weight: bold">TrackBoxStatus.xaml.cs</span>, Line 22, right after <br /><span style="font-style: italic">namespace TETControls.TrackBox</span>. Not the best place and solution I guess, but it works<br /><dl class="codebox"><dt>Code: </dt><dd><code>    <br />class MyCorrection<br />    {<br />        public static double &#91;&#93; ave_dist_arr = new double &#91;99999&#93;;//!!! Array of distances between pupils during calibration, 99999 is a max number of frames for calculation (may be much lower for sure)<br />        public static double ave_dist;//!!! Average distance between pupils during one frame<br />        public static int calib_samples_count;//!!! Count of frames in array<br />    }<br /></code></dd></dl><br /><br /><span style="font-weight: bold"><span style="text-decoration: underline">2.</span>Fill the array of distances between pupils during calibration</span>. I placed an addition to <span style="font-weight: bold">TrackBoxStatus.xaml.cs</span>, Line 145 (approximately), right inside <br /><span style="font-style: italic">public void OnGazeUpdate(GazeData gazeData)</span><br />Adding a condition on “calibration is processing” would be good but not necessary. The array should be filled in only during calibration, but I didnt find the right place due to absence of programming knowledge<br /><br /><dl class="codebox"><dt>Code: </dt><dd><code>            //!!! Filling the array<br />            if (TETControls.TrackBox.MyCorrection.calib_samples_count &lt; TETControls.TrackBox.MyCorrection.ave_dist_arr.Length)<br />                {<br />                    TETControls.TrackBox.MyCorrection.calib_samples_count += 1;<br />                    TETControls.TrackBox.MyCorrection.ave_dist_arr&#91;TETControls.TrackBox.MyCorrection.calib_samples_count&#93; = Math.Sqrt(Math.Pow((gazeData.RightEye.PupilCenterCoordinates.X - gazeData.LeftEye.PupilCenterCoordinates.X), 2) + Math.Pow((gazeData.RightEye.PupilCenterCoordinates.Y - gazeData.LeftEye.PupilCenterCoordinates.Y), 2));<br />                }//!!!</code></dd></dl><br /><br /><br /><span style="font-weight: bold"><span style="text-decoration: underline">3.</span>Renew all variables when calibration is started. </span>I placed the code into <span style="font-weight: bold">CalibrationRunner.xaml.cs</span>, Line 213 (approximately), right before <span style="font-style: italic">DoStart()</span>;<br /><br /><dl class="codebox"><dt>Code: </dt><dd><code>            //!!! Clear variables<br />            Array.Clear (TETControls.TrackBox.MyCorrection.ave_dist_arr, 0, 99999);//!!!<br />            TETControls.TrackBox.MyCorrection.calib_samples_count = 0;//!!!<br />            //!!!</code></dd></dl><br /><br /><br /><span style="font-weight: bold"><span style="text-decoration: underline">4.</span>Calculate the average distance between pupils during calibration based on array filled</span>. I placed the code into <span style="font-weight: bold">CalibrationRunner.xaml.cs</span>, Line 375 (approximately), right before <span style="font-style: italic">StopAndClose()</span>;<br /><br /><dl class="codebox"><dt>Code: </dt><dd><code>                //!!! Calculate average distance<br />                double sum = 0;<br />                int elem=0;<br />                for (int i = 0; i &lt; TETControls.TrackBox.MyCorrection.ave_dist_arr.Length; i++)<br />                {<br />                    if (TETControls.TrackBox.MyCorrection.ave_dist_arr&#91;i&#93;&gt;0)<br />                    {<br />                        sum = sum + TETControls.TrackBox.MyCorrection.ave_dist_arr&#91;i&#93;;<br />                        elem = elem + 1;<br />                    }<br />                }<br />                TETControls.TrackBox.MyCorrection.ave_dist = elem != 0 ? (double)sum / elem : 0;<br /><br />                Console.WriteLine(&quot;Done, average distance = &quot; + TETControls.TrackBox.MyCorrection.ave_dist);//!!!<br />                ///!!!</code></dd></dl><br /><br /><br /><br /><span style="font-weight: bold"><span style="text-decoration: underline">5.</span>Use calculated average distance to correct error in Mouse Control</span>. Replace screenX and screenY formula in <span style="font-weight: bold">CursorControl.cs</span>, Line 59 (approximately), with corrected one, like below. I know the formula is not very good, but the result is much better than one without correction. <span style="font-weight: bold"><span style="color: #FF0000">Please help with better correction formula.</span></span> The one I used is not very good and does not depend on screen area (but it should I guess). Anyway, in case distance between pupils does not change significantly, the correction does not correct coordinates significantly too<br /><br /><dl class="codebox"><dt>Code: </dt><dd><code>            //var screenY = (int)Math.Round(y + gY, 0); // Original formula<br />            //var screenX = (int)Math.Round(x + gX, 0); // Original formula<br />            //!!! Correction<br />            double pup_dist = Math.Sqrt(Math.Pow((gazeData.RightEye.PupilCenterCoordinates.X - gazeData.LeftEye.PupilCenterCoordinates.X), 2) + Math.Pow((gazeData.RightEye.PupilCenterCoordinates.Y - gazeData.LeftEye.PupilCenterCoordinates.Y), 2)); // pup_dist - current distance between pupils. If differs from the one during calibration, than the tracker calculates both X and Y wrongly<br />            double ave_d = TETControls.TrackBox.MyCorrection.ave_dist;<br />            if (ave_d == 0) ave_d = pup_dist; // if not calibrated during the session, ave_d = 0, correction would not work<br />            var screenY = (int)Math.Round(gazeData.RawCoordinates.Y - (gazeData.RawCoordinates.Y - ActiveScreen.Bounds.Height*1.25)*((pup_dist-ave_d)/ave_d)); // I would very appreciate if you advise better formula for Y. 1.25 means 1 (screenHeight) + 0.25 (distance from screen bottom to device)<br />            var screenX = (int)Math.Round(gazeData.RawCoordinates.X - (gazeData.RawCoordinates.X - ActiveScreen.Bounds.Width / 2) * ((pup_dist - ave_d) / ave_d)); // I would very appreciate if you advise better formula for X<br /><br />            //!!!</code></dd></dl><p>Statistics: Posted by <a href="http://theeyetribe.com/forum/memberlist.php?mode=viewprofile&amp;u=7725">skatak.aizenberg@gmail.com</a> — 22 Apr 2015, 12:54</p><hr />
]]></content>
</entry>
</feed>