PS there's a "cheap" way you can accomplish subpixel accuracy, as follows.  You basically take a bunch of 1D samples through the brightest pixel, looking at 2 neighbors in each direction, and then take a weighted sum of the results.  This calls the code I pasted in the last email.  It's not going to be as good as paraboloid regression, but it should allow you to test feasibility.
<br><br><br>// Do a 2D parabolic fit to give sub-pixel accuracy for translational<br>// registration, by performing four 1D parabolic fits through the closest<br>// integer correlation offset: horizontally, vertically, and on the leading
<br>// and trailing diagonals.  Take the weighted centroid of all four to get<br>// the true correlation offset.<br><br>// off_x and off_y are the one-pixel-accurate correlation offsets recovered<br>// by correlation.<br>
<br>// x1d and y1d are x and y values for the 1D quadratic fit function<br>double y1d[9] = {     // Get magnitudes at (off_x,off_y) and 8 neighbors<br>  dft_mag(dft, off_x - 1, off_y - 1),<br>  dft_mag(dft, off_x    , off_y - 1),
<br>  dft_mag(dft, off_x + 1, off_y - 1),<br>  dft_mag(dft, off_x - 1, off_y    ),<br>  dft_mag(dft, off_x    , off_y    ),<br>  dft_mag(dft, off_x + 1, off_y    ),<br>  dft_mag(dft, off_x - 1, off_y + 1),<br>  dft_mag(dft, off_x    , off_y + 1),
<br>  dft_mag(dft, off_x + 1, off_y + 1)<br>}<br><br>// Sum contributions to centroid of each quadratic fit<br>double x1d_tot = 0.0, y1d_tot = 0.0, x1d;<br><br>// Parabolic fit in horiz direction through correlation maximum
<br>x1d = parabolic_fit(-1, y1d[3], 0, y1d[4], 1, y1d[5]);<br>x1d_tot += x1d;<br><br>// Parabolic fit in horiz direction through correlation maximum<br>x1d = parabolic_fit(-1, y1d[1], 0, y1d[4], 1, y1d[7]);<br>y1d_tot += x1d;   // [x1d is x in parabola space, but y in correlation space]
<br><br>// Weight contributions of diagonal by the inverse of their distance<br>#define RT2_OV_2  0.7071067811865475244   // sqrt(2)/2  (= 1/sqrt(2))<br><br>// Parabolic fit in leading diagonal direction through correlation maximum
<br>x1d = parabolic_fit(-1, y1d[0], 0, y1d[4], 1, y1d[8]);<br>x1d_tot += x1d * RT2_OV_2;<br>y1d_tot += x1d * RT2_OV_2;<br><br>// Parabolic fit in leading diagonal direction through correlation maximum<br>x1d = parabolic_fit(-1, y1d[2], 0, y1d[4], 1, y1d[6]);
<br>x1d_tot -= x1d * RT2_OV_2;<br>y1d_tot += x1d * RT2_OV_2;<br><br>// Take centroid of all parabolic fits, weighting diagonals by RT2_OV_2;<br>// make relative to correlation coords by adding off_x, off_y<br>double subpix_off_x = off_x + x1d_tot / (
2.0 + 2.0 * RT2_OV_2);<br>double subpix_off_y = off_y + y1d_tot / (2.0 + 2.0 * RT2_OV_2);<br><br><br><br><div><span class="gmail_quote">On 9/5/07, <b class="gmail_sendername">Luke Hutchison</b> <<a href="mailto:luke.hutch@gmail.com">
luke.hutch@gmail.com</a>> wrote:</span><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">Where do you get the size 90x30 from though?  Are you saying you can't get at the full-sized frame through the API currently?
<br><br>You really should consider fitting a paraboloid over the dot to get sub-pixel resolution.  Note that if the dot is bigger (more than a few pixels), you probably want to just use the weighted centroid, but if it's small, a paraboloid is the right approach.  You really will get at least a 10x increase in accuracy in both x and y, bringing your effective resolution to something like 900x300 for the example you gave.  You may not even need a lens.  I have used this before with success for an image processing project.
<br><br>Here's the code for the 1D version:<br><br>// Fit a parabola to three points, and return the x coord of the turning<br>// point (point 2 is the central point, points 1 and 3 are its neighbors)<br>double parabolic_fit(double x1, double y1,
<br>                     double x2, double y2,<br>                     double x3, double y3) {<br><br>  double a = (y3 - y2) / ((x3 - x2) * (x3 - x1)) -<br>             (y1 - y2) / ((x1 - x2) * (x3 - x1));<br><br>  double b = (y1 - y2 + a * (x2 * x2 - x1 * x1)) / (x1 - x2);
<br><br>  double xmin = x2;       // Just use central point if parabola is flat<br>  if (fabs(a) > EPSILON)<br>    xmin = -b / (2 * a);  // [avoids division by zero]<br><br>  // Use the following to calculate the y-value at the turning point
<br>  // of the parabola:<br>  //<br>  //   double c = y1 - a * x1 * x1 - b * x1;<br>  //   double ymin = a * xmin * xmin + b * xmin + c;<br><br>  return xmin;<br>}<br><br>I don't have code for the 2D version unfortunately.
<br><br>The 2D version (fitting a paraboloid to a neighborhood of more than four points total) is overspecified, as is the 1D version if fitting a parabola to more than three points (e.g. using two neighbors on either side of the brightest pixel).  Thus you need to do some sort of regression to find the best fit.  I'm sure there is code out there to accomplish this.
<br><span class="sg"><br>Luke</span><div><span class="e" id="q_114d69428e411cc6_2"><br><br><br><div><span class="gmail_quote">On 9/5/07, <b class="gmail_sendername"><a href="mailto:linaccess@yokoy.de" target="_blank" onclick="return top.js.OpenExtLink(window,event,this)">
linaccess@yokoy.de</a></b> <<a href="mailto:linaccess@yokoy.de" target="_blank" onclick="return top.js.OpenExtLink(window,event,this)">linaccess@yokoy.de</a>> wrote:
</span><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">Hello Luke,<br><br>On Tue, 4 Sep 2007 16:11:34 -0700<br>"Luke Hutchison" <
<a href="mailto:luke.hutch@gmail.com" target="_blank" onclick="return top.js.OpenExtLink(window,event,this)">luke.hutch@gmail.com</a>> wrote:<br><br>> Is the processing time for 640x480 the reason you're only using 90x30?
<br>><br><br>No, I am not at the point thinking about optimization the processing time.
<br>You don't want to dance in front of the camera to control the mouse pointer. You just want to move your head a few degrees as if you would look to the edges of the display without moving your eyes. Then the area recognized from the camera is very small. It is like moving the mouse only one or two millimeters to move the mousepointer over the whole desktop. To get more 'delta pixel' I need a mag lens, I think.
<br><br>regards,<br><br>yokoy<br><br><br><br>> You can actually dramatically increase the precision to which you can read<br>> back the bright point's location by fitting a paraboloid to the intensity<br>> values in the neighborhood of the brightest pixel, then reading off the
<br>> location of the extremum of the paraboloid.  You will get at least one order<br>> of magnitude more accuracy that way than looking at the integer coords of<br>> the brightest pixel (perhaps as much as two orders of magnitude).
<br>><br>> Luke<br>><br>><br>> On 9/4/07, <a href="mailto:linaccess@yokoy.de" target="_blank" onclick="return top.js.OpenExtLink(window,event,this)">linaccess@yokoy.de</a> <<a href="mailto:linaccess@yokoy.de" target="_blank" onclick="return top.js.OpenExtLink(window,event,this)">
linaccess@yokoy.de</a>> wrote:<br>> ><br>> > Hello Mary Lou,
<br>> ><br>> > On Tue, 04 Sep 2007 12:13:34 -0400<br>> > Mary Lou Jepsen <<a href="mailto:mljatolpc@gmail.com" target="_blank" onclick="return top.js.OpenExtLink(window,event,this)">mljatolpc@gmail.com
</a>> wrote:<br>> ><br>> > > lenses are cheap.  it depends on what exactly you are doing with the
<br>> > > software.<br>> ><br>> > tracking a little shiny point at the head and transform it into<br>> > mousepointer movements. Here is the description:<br>> > <a href="http://www.olpcaustria.org/mediawiki/index.php/Headtracker" target="_blank" onclick="return top.js.OpenExtLink(window,event,this)">

http://www.olpcaustria.org/mediawiki/index.php/Headtracker</a><br>> ><br>> > With the XO camera we typicaly use only 90x30 pixel from the 640x480<br>> > pixel. So I want to magnify the operative area with a lens.
<br>> > Here is a picture of the area:<br>> ><br>> > <a href="http://www.olpcaustria.org/mediawiki/index.php/Headtracker#magnification_lens" target="_blank" onclick="return top.js.OpenExtLink(window,event,this)">
http://www.olpcaustria.org/mediawiki/index.php/Headtracker#magnification_lens
</a><br>> ><br>> ><br>> ><br>> > > American Science and Surplus is a good way to experiment:<br>> > > <a href="http://sciplus.com/category.cfm?subsection=21" target="_blank" onclick="return top.js.OpenExtLink(window,event,this)">
http://sciplus.com/category.cfm?subsection=21
</a><br>> > ><br>> ><br>> > thank you for that link. A plastic lens is what I am searching for.<br>> ><br>> ><br>> > > then to china for mass production at very low price point.<br>

> > ><br>> > ><br>> > > - Mary Lou<br>> > ><br>> > ><br>> ><br>> > regards,<br>> ><br>> > yokoy<br>> > --<br>> ><br>> > _______________________________________________
<br>> > Devel mailing list<br>> > <a href="mailto:Devel@lists.laptop.org" target="_blank" onclick="return top.js.OpenExtLink(window,event,this)">Devel@lists.laptop.org</a><br>> > <a href="http://lists.laptop.org/listinfo/devel" target="_blank" onclick="return top.js.OpenExtLink(window,event,this)">
http://lists.laptop.org/listinfo/devel</a><br>
> ><br>><br><br><br>--<br><br></blockquote></div><br>
</span></div></blockquote></div><br>