root/exactrbn/trunk/src/calibrate.cpp

Revision 669, 10.7 kB (checked in by tapted, 2 years ago)

Add a copyright notice

  • Property svn:eol-style set to native
  • Property svn:keywords set to author date id revision url Rev Revision
Line 
1/* $Id$ $URL$ */
2
3/**\file calibrate.cpp
4 * A screen calibration program using / demonstrator of
5 * an exact-interpolation radial basis function neural network.
6 * Copyright Trent Apted 2008 All rights reserved.
7 *
8 * \author Trent Apted <tapted@it.usyd.edu.au>
9 * \version $Revision$
10 * \date $Date$
11 */
12
13
14#include <SDL/SDL.h> //for SDL_Surface, events, etc.
15#include <unistd.h>  //for size_t, usleep
16
17#include <deque>    //for points queue
18#include <vector>
19#include <utility>  //for std::pair
20#include <fstream>
21#include <iostream>
22
23
24/** #define VDEBUG for verbose debugging in rbn_solve.h */
25//#define VDEBUG
26//#define DEBUG
27#include "rbn_solve.h"
28
29using std::make_pair;
30
31/** Configuration namespace */
32namespace Config {
33    int TARGET_SCREEN_WIDTH = 1024; ///< Width of the SDL surface
34    int TARGET_SCREEN_HEIGHT = 768; ///< Height of the SDL Surface
35    int BOX_SIZE = 20;      ///< Width of the calibration squares
36    int TARGET_SCREEN_BPP = 24; ///< Colour depth of the SDL Surface
37    int DIFF = 32;          ///< Distance between calibration squares
38    float FROM_EDGE = 0.05; ///< Portion from edge of screen at which calibrations squares are drawn
39    bool FULLSCREEN = false;///< Whether to enter fullscreen mode
40    bool SHOWPIXELS = true; ///< Whether to show mouse movement events to stderr
41
42    int MAXDIM = 9;         ///< Maximum number of calibration points
43    double SIGMA = 10;      ///< Value of sigma for the RBF Network
44}
45using namespace Config;
46
47/** define LATTICEPATTERN to produce a line grid, rather than dots */
48#define LATTICEPATTERN
49
50static SDL_Surface *surf; ///< The SDL surface / screen display handle
51
52static SDL_Surface *makeSurface(); ///< startup function -- load window
53
54
55/** does nothing..? */
56static void clearTouch() {}
57/** return/assign the next emulated touch */
58static void getTouch(int &row, int &col) {
59    SDL_Event event;
60    bool terminate = false;
61    while (!terminate && SDL_WaitEvent(&event)) {
62        switch(event.type) {
63        case SDL_QUIT:
64            exit(1);
65        case SDL_MOUSEBUTTONDOWN: break;
66        case SDL_MOUSEBUTTONUP:
67            //terminate = handleButton(event.button);
68            col = event.button.x;
69            row = event.button.y;
70            terminate = true;
71            break;
72        case SDL_MOUSEMOTION:
73            if (SHOWPIXELS)
74                fprintf(stderr, "\033[`(%d, %d)    ", event.motion.x, event.motion.y);
75        case SDL_KEYUP:
76            if (event.key.keysym.sym == SDLK_ESCAPE)
77                exit(1);
78        case SDL_KEYDOWN:
79            break;
80        case SDL_USEREVENT:
81            break;
82        default:
83            break;
84        }
85    }
86}
87
88/** Add a point to the callibration */
89static void doPoint (const double x, const double y, XYInterp &ts) {
90    SDL_LockSurface(surf);
91
92    static std::vector<SDL_Rect> points; ///< Remeber past points for display
93
94    const Uint32 BLACK = SDL_MapRGB(surf->format, 0, 0, 0);
95    const Uint32 CYAN = SDL_MapRGB(surf->format, 0, 255, 255);
96    const Uint32 YELLOW = SDL_MapRGB(surf->format, 255, 255, 0);
97    const Uint32 RED = SDL_MapRGB(surf->format, 255, 0, 255);
98
99    SDL_Rect r;
100    int tr, tc;
101    r.w = BOX_SIZE;
102    r.h = BOX_SIZE;
103
104    XYInterp::EXAMPLE ex;
105
106    ex.out[0] = 1.0 * static_cast<Sint16>(x + 0.49) / surf->w;
107    ex.out[1] = 1.0 * static_cast<Sint16>(y + 0.49) / surf->h;
108
109    SDL_Rect rr;
110    rr.x = static_cast<Sint16>(x + 0.49) - 1;
111    rr.y = static_cast<Sint16>(y + 0.49) - 1;
112    rr.w = 3;
113    rr.h = 3;
114
115    r.x = static_cast<Sint16>(x - (BOX_SIZE / 2) + 0.49);
116    r.y = static_cast<Sint16>(y - (BOX_SIZE / 2) + 0.49);
117
118    SDL_FillRect(surf, &r, static_cast<Uint32>(CYAN));
119    for (std::vector<SDL_Rect>::iterator it = points.begin(); it!=points.end();++it)
120        SDL_FillRect(surf, &*it, static_cast<Uint32>(RED));
121    SDL_UnlockSurface(surf);
122    r.x = r.y = 0;
123    r.w = surf->w;
124    r.h = surf->h;
125    SDL_UpdateRects(surf, 1, &r);
126    //SDL_UpdateRects(surf, 1, &r);
127
128    points.push_back(rr);
129
130    clearTouch();
131    getTouch(tr, tc);
132
133    ex.in[0] = 1.0 * tc / surf->w;
134    ex.in[1] = 1.0 * tr / surf->h;
135
136    //usleep(1000000);
137    r.x = r.y = 0;
138    r.w = surf->w;
139    r.h = surf->h;
140    SDL_LockSurface(surf);
141    SDL_FillRect(surf, &r, (Uint32)BLACK);
142    //for (std::vector<SDL_Rect>::iterator it = points.begin(); it!=points.end();++it)
143    //    SDL_FillRect(surf, &*it, reinterpret_cast<Uint32>(RED));
144    SDL_UnlockSurface(surf);
145    //SDL_UpdateRects(surf, 1, &r);
146    ts.addExample(ex);
147    ts.solve();
148    fprintf(stderr, "\n(%f, %f) <- (%f, %f)\n", ex.in[0], ex.in[1], ex.out[0], ex.out[1]);
149    ts.sub(ex.out, ex.in);
150    fprintf(stderr, "(%f, %f) -> (%f, %f)\n", ex.in[0], ex.in[1], ex.out[0], ex.out[1]);
151    r.w = r.h = 1;
152    for (r.x = DIFF/2; r.x < surf->w; r.x+=DIFF) {
153        for (r.y = DIFF/2; r.y < surf->h; r.y+=DIFF) {
154#ifdef LATTICEPATTERN
155            int mx = r.x+DIFF;
156            int my = r.y+DIFF;
157            for (int iter = 0; iter < 2; ++iter) {
158                for (; (iter?r.x:r.y) < (iter?mx:my); (iter?r.x:r.y)++) {
159#endif
160            XYInterp::INVEC in;
161            in[0] = 1.0*r.x/surf->w;
162            in[1] = 1.0*r.y/surf->h;
163            XYInterp::OUTVEC out;
164            ts.sub(out, in);
165            //fprintf(stderr, "(%f, %f) -> (%f, %f)\n", in[0], in[1], out[0], out[1]);
166            SDL_Rect r2 = r;
167            r2.x = static_cast<Sint16>(surf->w*out[0] + 0.49);
168            r2.y = static_cast<Sint16>(surf->h*out[1] + 0.49);
169
170            SDL_FillRect(surf, &r2, static_cast<Uint32>(YELLOW));
171#ifdef LATTICEPATTERN
172                }
173                r.x = mx-DIFF;
174                r.y = my-DIFF;
175            }
176#endif
177        }
178    }
179    r.x = r.y = 0;
180    r.w = surf->w;
181    r.h = surf->h;
182    SDL_UpdateRects(surf, 1, &r);
183}
184
185
186struct Quad {
187    double xmin, xmax, ymin, ymax, xhalf, yhalf;
188
189    Quad(double xn, double xx, double yn, double ym)
190        :
191    xmin(xn), xmax(xx), ymin(yn), ymax(ym), xhalf((xmin+xmax)*0.5), yhalf((ymin+ymax)*0.5)
192    {
193
194    }
195
196    Quad nw() const {return Quad(xmin, xhalf, ymin, yhalf);}
197    Quad ne() const {return Quad(xhalf, xmax, ymin, yhalf);}
198    Quad se() const {return Quad(xhalf, xmax, yhalf, ymax);}
199    Quad sw() const {return Quad(xmin, xhalf, yhalf, ymax);}
200};
201
202enum {
203    W = 0x1,
204    N = 0x2,
205    E = 0x4,
206    S = 0x8
207};
208
209
210/** Pending queue of points to "do" */
211static std::deque<std::pair<Quad, int> > points;
212
213/**
214 * Arbitrarily divide up a rectangular region / Quad into subregions and queue
215 * points at the centre the midpoints of the edges, such that no point is
216 * ever done twice.
217 */
218static void divide(XYInterp &ts, const Quad &q, int quads = 0xf) {
219    if (quads & W)
220        doPoint(q.xmin, q.yhalf, ts);
221    if (quads & N)
222        doPoint(q.xhalf, q.ymin, ts);
223    if (quads & E)
224        doPoint(q.xmax, q.yhalf, ts);
225    if (quads & S)
226        doPoint(q.xhalf, q.ymax, ts);
227
228    doPoint(q.xhalf, q.yhalf, ts);
229
230    if ((int)(points.size()*4 + ts.dim()) < MAXDIM) {
231        points.push_back(make_pair(q.nw(), quads&(N|S|E|W)));
232        points.push_back(make_pair(q.ne(), quads&(N|E|S)));
233        points.push_back(make_pair(q.se(), quads&(E|S)));
234        points.push_back(make_pair(q.sw(), quads&(W|E|S)));
235    }
236}
237
238/** Print out the usage to stderr */
239static void usage(const char* argv0) {
240    fprintf(stderr, "Usage: %s [<width=%d> <height=%d> [sigma=%f [numpoints=%d] ] ]\n",
241            argv0,
242            TARGET_SCREEN_WIDTH,
243            TARGET_SCREEN_HEIGHT,
244            SIGMA,
245            MAXDIM);
246}
247
248
249/**
250 * Callibaration test program main()
251 */
252int main(int argc, char **argv) {
253    atexit(&SDL_Quit);
254    if (argc > 2) {
255        TARGET_SCREEN_WIDTH = atoi(argv[1]);
256        TARGET_SCREEN_HEIGHT = atoi(argv[2]);
257    }
258    if (TARGET_SCREEN_WIDTH <= 0 ||
259        TARGET_SCREEN_HEIGHT <= 0) {
260        usage(argv[0]);
261        return 1;
262    }
263    surf = makeSurface();
264
265    if (!surf) {
266        return 2;
267    }
268
269    if (argc > 3)
270        SIGMA = atof(argv[3]);
271    if (argc > 4)
272        MAXDIM = atoi(argv[4]);
273
274    usage(argv[0]);
275
276    usleep(1000000);
277
278//    if (argc > 1 && strcmp(argv[1], "-t") == 0)
279//        return replay();
280
281    /* four corners */
282    XYInterp ts(SIGMA);
283    //XYInterp ts("network.dat");
284    double xmin = surf->w*FROM_EDGE;
285    double xmax = surf->w - surf->w*FROM_EDGE;
286    double ymin = surf->h*FROM_EDGE;
287    double ymax = surf->h - surf->h*FROM_EDGE;
288
289    doPoint(xmin, ymin, ts);
290    doPoint(xmax, ymin, ts);
291    doPoint(xmax, ymax, ts);
292    doPoint(xmin, ymax, ts);
293
294    /* midpoints */
295    points.push_back(make_pair(Quad(xmin, xmax, ymin, ymax), N|S|E|W));
296
297    while (!points.empty()) {
298        divide(ts, points.front().first, points.front().second);
299        points.pop_front();
300    }
301
302    {
303        std::ofstream f("network.dat");
304        f << ts << std::endl;
305    }
306    {
307        std::ifstream f("network.dat");
308        XYInterp xyi(f);
309        std::cerr << xyi << std::endl;
310    }
311
312    usleep(5000000);
313
314}
315
316static SDL_Surface *makeSurface() {
317    int videoFlags = 0;                  // Flags to pass to SDL_SetVideoMode
318    const SDL_VideoInfo *videoInfo;      // this holds some info about our display
319    SDL_Surface *ret;
320
321    /* initialize SDL */
322    if ( SDL_Init( SDL_INIT_VIDEO ) < 0 ) {
323        fprintf( stderr, "Video initialization failed: %s\n", SDL_GetError( ) );
324        return 0;
325    }
326    if (!(videoInfo = SDL_GetVideoInfo( ))) {
327        fprintf( stderr, "Video query failed: %s\n", SDL_GetError( ) );
328        return 0;
329    }
330    /* the flags to pass to SDL_SetVideoMode */
331//    videoFlags  = SDL_OPENGL;          /* Enable OpenGL in SDL */
332//    videoFlags |= SDL_GL_DOUBLEBUFFER; /* Enable double buffering */
333    videoFlags |= SDL_HWPALETTE;       /* Store the palette in hardware */
334//    videoFlags |= SDL_RESIZABLE;       /* Enable window resizing */
335//    if (TRY_FULLSCREEN)
336
337    if (FULLSCREEN)
338        videoFlags |= SDL_FULLSCREEN;
339
340    /* This checks to see if surfaces can be stored in memory */
341    videoFlags |= videoInfo->hw_available ? SDL_HWSURFACE : SDL_SWSURFACE;
342    /* This checks if hardware blits can be done */
343    if (videoInfo->blit_hw) videoFlags |= SDL_HWACCEL;
344    /* Sets up OpenGL double buffering */
345//    SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
346
347    /* Set up FSAA */
348    /*
349    if (RConfig::TARGET_FSAA > 0) {
350        int fsaa = RConfig::TARGET_FSAA;
351        while (fsaa > 0 && SDL_GL_SetAttribute (SDL_GL_SAMPLES_SIZE, fsaa)
352            --fsaa;
353        fprintf(stderr, "Using %dx FSAA\n", fsaa);
354    }*/
355
356    /* get a SDL surface */
357    ret = SDL_SetVideoMode( TARGET_SCREEN_WIDTH, TARGET_SCREEN_HEIGHT, TARGET_SCREEN_BPP, videoFlags );
358    if (!ret) {
359        fprintf( stderr,  "Video mode set failed: %s\n", SDL_GetError( ) );
360        return 0;
361    }
362    if (videoFlags & SDL_HWSURFACE) {
363        fprintf(stderr, "Using hardware accelleration\n");
364    }
365    return ret;
366}
367
368extern "C" {
369    int MAIN__() {
370        return 1;
371    }
372}
Note: See TracBrowser for help on using the browser.