Subversion Repositories AndroidProjects

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
204 chris 1
/*
2
 *
3
 * This file is part of ARToolKit.
4
 *
5
 * ARToolKit is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation; either version 2 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * ARToolKit is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with ARToolKit; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
 *
19
 */
20
 
21
// ============================================================================
22
//      Includes
23
// ============================================================================
24
 
25
#ifdef _WIN32
26
#  include <windows.h>
27
#endif
28
#include <math.h>
29
#include <stdio.h>
30
#include <stdlib.h>
31
#include <string.h>
32
#ifndef __APPLE__
33
#  include <GL/glut.h>
34
#  ifdef GL_VERSION_1_2
35
#    include <GL/glext.h>
36
#  endif
37
#else
38
#  include <GLUT/glut.h>
39
#  include <OpenGL/glext.h>
40
#endif
41
#include <AR/config.h>
42
#include <AR/ar.h>
43
#include <AR/video.h>
44
#include <AR/param.h>
45
#include <AR/gsub_lite.h>
46
#include "calib_cparam.h"
47
 
48
// ============================================================================
49
//      Constants
50
// ============================================================================
51
 
52
#define CALIB_CPARAM_DEBUG 0
53
 
54
// ============================================================================
55
//      Global variables
56
// ============================================================================
57
 
58
/* set up the video format globals */
59
 
60
#if defined(__sgi)
61
char            *vconf = "-size=FULL";
62
#elif defined(__linux)
63
#  if defined(AR_INPUT_GSTREAMER)
64
char                    *vconf = "videotestsrc";
65
#  elif defined(AR_INPUT_V4L)
66
char            *vconf = "-width=640 -height=480";
67
#  elif defined(AR_INPUT_1394CAM)
68
char            *vconf = "-mode=640x480_YUV411";
69
#  elif defined(AR_INPUT_DV)
70
char            *vconf = "";
71
#  endif
72
#elif defined(_WIN32)
73
char                    *vconf = "Data\\WDM_camera_flipV.xml";
74
#elif defined(__APPLE__)
75
char                    *vconf = "-width=640 -height=480";
76
#else
77
char                    *vconf = "";
78
#endif
79
 
80
static ARUint8          *gARTImage = NULL;
81
static ARParam          gARTCparam; // Dummy parameter, to supply to gsub_lite.
82
static ARGL_CONTEXT_SETTINGS_REF gArglSettings = NULL;
83
 
84
static int             gWin;
85
static int             gXsize = 0;
86
static int             gYsize = 0;
87
int             refresh;
88
 
89
static unsigned char   *gSaveARTImage = NULL;
90
static ARGL_CONTEXT_SETTINGS_REF gSaveArglSettings = NULL;
91
 
92
static ARParam         param;
93
static double          dist_factor[4];
94
 
95
int             line_num;
96
int             loop_num;
97
int             line_mode[LINE_MAX];
98
double          inter_coord[LOOP_MAX][LINE_MAX][LINE_MAX][3];
99
double          line_info[LOOP_MAX][LINE_MAX][4];
100
 
101
int             mode;
102
int             line_num_current;
103
int             loop_num_current;
104
double          theta;
105
double          radius;
106
double          gStartX, gStartY, gEndX, gEndY;
107
 
108
// ============================================================================
109
//      Functions
110
// ============================================================================
111
 
112
int             main(int argc, char *argv[]);
113
static int      init(int argc, char *argv[]);
114
static void             Keyboard(unsigned char key, int x, int y);
115
static void             Special(int key, int x, int y);
116
static void             Mouse(int button, int state, int x, int y);
117
static void     Quit(void);
118
static void     Idle(void);
119
static void     Visibility(int visible);
120
static void     Reshape(int w, int h);
121
static void     Display(void);
122
static void             drawPrevLine(void);
123
static void             drawNextLine(void);
124
static void             draw_warp_line(double sx, double ex, double sy, double ey);
125
static void             getCpara(void);
126
static void             intersection( double line1[4], double line2[4], double *screen_coord );
127
 
128
 
129
int main(int argc, char *argv[])
130
{
131
        glutInit(&argc, argv);
132
    if (!init(argc, argv)) exit(-1);
133
 
134
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
135
    glutInitWindowSize(gXsize, gYsize);
136
    glutInitWindowPosition(100,100);
137
    gWin = glutCreateWindow("Camera calibration");
138
 
139
        // Setup argl library for current context.
140
        // Turn off distortion compensation.. we are calibrating.
141
        if ((gArglSettings = arglSetupForCurrentContext()) == NULL) {
142
                fprintf(stderr, "main(): arglSetupForCurrentContext() returned error.\n");
143
                exit(-1);
144
        }
145
        arglDistortionCompensationSet(gArglSettings, FALSE);
146
 
147
        // Make a dummy camera parameter to supply when calling arglDispImage().
148
        gARTCparam.xsize = gXsize;
149
        gARTCparam.ysize = gYsize;
150
 
151
        // Setup a space to save our captured image.
152
        if ((gSaveArglSettings = arglSetupForCurrentContext()) == NULL) {
153
                fprintf(stderr, "grabImage(): arglSetupForCurrentContext() returned error.\n");
154
                exit(-1);
155
        }
156
        arglDistortionCompensationSet(gSaveArglSettings, FALSE);
157
        arMalloc(gSaveARTImage, unsigned char, gXsize*gYsize*AR_PIX_SIZE_DEFAULT);
158
 
159
        // Register GLUT event-handling callbacks.
160
        // NB: Idle() is registered by Visibility.
161
    glutDisplayFunc(Display);
162
        glutReshapeFunc(Reshape);
163
        glutVisibilityFunc(Visibility);
164
        glutKeyboardFunc(Keyboard);
165
        glutSpecialFunc(Special);
166
    glutMouseFunc(Mouse);
167
 
168
        if (arVideoCapStart() != 0) {
169
        fprintf(stderr, "init(): Unable to begin camera data capture.\n");
170
                return (FALSE);        
171
        }
172
        mode = 0;
173
    line_num_current = 0;
174
    loop_num_current = 0;
175
 
176
    glutMainLoop();
177
        return (0);
178
}
179
 
180
static int init(int argc, char *argv[])
181
{
182
    printf("Input center coordinates: X = ");
183
    scanf("%lf", &dist_factor[0]);
184
    while (getchar() != '\n');
185
    printf("                        : Y = ");
186
    scanf("%lf", &dist_factor[1]);
187
    while (getchar() != '\n');
188
    printf("Input distortion ratio: F = ");
189
    scanf("%lf", &dist_factor[2]);
190
    while (getchar() != '\n');
191
    printf("Input size adjustment factor: S = ");
192
    scanf("%lf", &dist_factor[3]);
193
    while (getchar() != '\n');
194
 
195
    initLineModel(&line_num, &loop_num, line_mode, inter_coord);
196
 
197
        // Open the video path.
198
    if (arVideoOpen(vconf) < 0) {
199
        fprintf(stderr, "init(): Unable to open connection to camera.\n");
200
        return (FALSE);
201
        }
202
 
203
        // Find the size of the window.
204
    if (arVideoInqSize(&gXsize, &gYsize) < 0) return (FALSE);
205
    fprintf(stdout, "Camera image size (x,y) = (%d,%d)\n", gXsize, gYsize);
206
 
207
        // Allocate space for a save image.
208
        arMalloc(gSaveARTImage, unsigned char, gXsize * gYsize * AR_PIX_SIZE_DEFAULT);
209
 
210
    param.xsize = gXsize;
211
    param.ysize = gYsize;
212
    param.dist_factor[0] = dist_factor[0];
213
    param.dist_factor[1] = dist_factor[1];
214
    param.dist_factor[2] = dist_factor[2];
215
    param.dist_factor[3] = dist_factor[3];
216
 
217
        return (TRUE);
218
}
219
 
220
static void thetaRadiusSet(void) {
221
        if (line_num_current == 0) {
222
                if (line_mode[line_num_current] == L_HORIZONTAL) {
223
                        theta  = 90;
224
                        radius = gYsize/2;
225
                } else {
226
                        theta  = 0;
227
                        radius = gXsize/2;
228
                }
229
        } else {
230
                if (line_mode[line_num_current] == L_HORIZONTAL) {
231
                        if (line_mode[line_num_current] == line_mode[line_num_current-1]) {
232
                                radius += 10.0;
233
                        } else {
234
                                theta  = 90;
235
                                radius = gYsize/2;
236
                        }
237
                } else {
238
                        if (line_mode[line_num_current] == line_mode[line_num_current-1]) {
239
                                radius += 10.0;
240
                        } else {
241
                                theta  = 0;
242
                                radius = gXsize/2;
243
                        }
244
                }
245
        }
246
}
247
 
248
static void eventCancel(void) {
249
        if (mode == 0) {
250
                // Cancel from mode 0 should quit program.
251
                arVideoCapStop();
252
                Quit();
253
        } else if (mode == 1) {
254
                if (line_num_current == 0) {
255
                        // Cancel from mode 1, first line, should go back to mode 0.
256
                        arVideoCapStart();
257
                        mode = 0;                      
258
                } else {
259
                        // Cancel from mode 1, non-first line, should go back to first line.
260
                        line_num_current = 0;
261
                        thetaRadiusSet();
262
                        glutPostRedisplay();
263
                }
264
        }
265
}
266
 
267
static void Mouse(int button, int state, int x, int y)
268
{
269
        ARUint8 *image;
270
 
271
        if (state == GLUT_DOWN) {
272
                if (button == GLUT_RIGHT_BUTTON) {
273
                        eventCancel();
274
                } else if (button == GLUT_LEFT_BUTTON && mode == 0) {
275
                        // Processing a new image.
276
                        // Copy an image to saved image buffer.
277
                        do {
278
                                image = arVideoGetImage();
279
                        } while (image == NULL);
280
                        memcpy(gSaveARTImage, image, gXsize*gYsize*AR_PIX_SIZE_DEFAULT);
281
                        printf("Grabbed image.\n");
282
                        arVideoCapStop();
283
                        mode = 1;
284
                        line_num_current = 0;
285
                        thetaRadiusSet();
286
                        glutPostRedisplay();
287
                }
288
        }
289
}
290
 
291
static void Keyboard(unsigned char key, int x, int y)
292
{
293
    ARParam  iparam;
294
    double   trans[3][4];
295
    char     name[256];
296
    int      k = 1;
297
 
298
    if( mode == 0 ) return;
299
 
300
    switch( key ) {
301
        case 0x1B:
302
            gStartX = -1.0;
303
            gStartY = -1.0;
304
            gEndX = -1.0;
305
            gEndY = -1.0;
306
                        // fall through..
307
        case 0x0D:
308
            line_info[loop_num_current][line_num_current][0] = gStartX;
309
            line_info[loop_num_current][line_num_current][1] = gStartY;
310
            line_info[loop_num_current][line_num_current][2] = gEndX;
311
            line_info[loop_num_current][line_num_current][3] = gEndY;
312
            line_num_current++;
313
                        if (line_num_current < line_num) {
314
                                thetaRadiusSet();
315
            } else {
316
                                // Completed placements for this image.
317
                loop_num_current++;
318
                if (loop_num_current < loop_num) {
319
                    arVideoCapStart();
320
                    mode = 0;
321
                } else {
322
                                        // All done. Calculate parameter, save it, and exit.
323
                                        getCpara();
324
                                        arParamDecomp( &param, &iparam, trans );
325
                                        arParamDisp( &iparam );
326
 
327
                                        printf("Input filename: ");
328
                                        scanf("%s", name);
329
                                        arParamSave( name, 1, &iparam );
330
 
331
                                        Quit();
332
                                }
333
            }
334
            break;
335
        default:
336
            k = 0;
337
            break;
338
    }
339
    if (k) glutPostRedisplay();
340
}
341
 
342
 
343
static void Special(int key, int x, int y)
344
{
345
    double   mx, my;
346
    int      k = 1;
347
 
348
    if (mode == 0) return;
349
 
350
    if (line_mode[line_num_current] == L_HORIZONTAL) {
351
        switch (key) {
352
            case GLUT_KEY_UP:
353
                radius -= 1.0;
354
                break;
355
            case GLUT_KEY_DOWN:
356
                radius += 1.0;
357
                break;
358
            case GLUT_KEY_LEFT:
359
                mx = (gStartX + gEndX)/ 2.0;
360
                my = (gStartY + gEndY)/ 2.0;
361
                theta -= 0.25;
362
                radius = cos( (double)(theta*3.141592/180.0) ) * mx
363
                       + sin( (double)(theta*3.141592/180.0) ) * my;
364
                break;
365
            case GLUT_KEY_RIGHT:
366
                mx = (gStartX + gEndX)/ 2.0;
367
                my = (gStartY + gEndY)/ 2.0;
368
                theta += 0.25;
369
                radius = cos( (double)(theta*3.141592/180.0) ) * mx
370
                       + sin( (double)(theta*3.141592/180.0) ) * my;
371
                break;
372
            default:
373
                k = 0;
374
                break;
375
        }
376
    } else {
377
        switch (key) {
378
            case GLUT_KEY_UP:
379
                mx = (gStartX + gEndX)/ 2.0;
380
                my = (gStartY + gEndY)/ 2.0;
381
                theta += 0.25;
382
                radius = cos( (double)(theta*3.141592/180.0) ) * mx
383
                       + sin( (double)(theta*3.141592/180.0) ) * my;
384
                break;
385
            case GLUT_KEY_DOWN:
386
                mx = (gStartX + gEndX)/ 2.0;
387
                my = (gStartY + gEndY)/ 2.0;
388
                theta -= 0.25;
389
                radius = cos( (double)(theta*3.141592/180.0) ) * mx
390
                       + sin( (double)(theta*3.141592/180.0) ) * my;
391
                break;
392
            case GLUT_KEY_LEFT:
393
                radius -= 1.0;
394
                break;
395
            case GLUT_KEY_RIGHT:
396
                radius += 1.0;
397
                break;
398
            default:
399
                k = 0;
400
                break;
401
        }
402
    }
403
 
404
    if (k) glutPostRedisplay();
405
}
406
 
407
static void Quit(void)
408
{
409
        if (gSaveArglSettings) arglCleanup(gSaveArglSettings);
410
        if (gArglSettings) arglCleanup(gArglSettings);
411
        if (gWin) glutDestroyWindow(gWin);
412
        arVideoClose();
413
        exit(0);
414
}
415
 
416
static void Idle(void)
417
{
418
        static int ms_prev;
419
        int ms;
420
        float s_elapsed;
421
        ARUint8 *image;
422
 
423
        // Find out how long since Idle() last ran.
424
        ms = glutGet(GLUT_ELAPSED_TIME);
425
        s_elapsed = (float)(ms - ms_prev) * 0.001;
426
        if (s_elapsed < 0.01f) return; // Don't update more often than 100 Hz.
427
        ms_prev = ms;
428
 
429
        // Grab a video frame.
430
        if (mode == 0) {
431
                if ((image = arVideoGetImage()) != NULL) {
432
                        gARTImage = image;
433
                        // Tell GLUT the display has changed.
434
                        glutPostRedisplay();
435
                }      
436
        }
437
}
438
 
439
//
440
//      This function is called on events when the visibility of the
441
//      GLUT window changes (including when it first becomes visible).
442
//
443
static void Visibility(int visible)
444
{
445
        if (visible == GLUT_VISIBLE) {
446
                glutIdleFunc(Idle);
447
        } else {
448
                glutIdleFunc(NULL);
449
        }
450
}
451
 
452
//
453
//      This function is called when the
454
//      GLUT window is resized.
455
//
456
static void Reshape(int w, int h)
457
{
458
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
459
        glViewport(0, 0, (GLsizei) w, (GLsizei) h);
460
 
461
        glMatrixMode(GL_PROJECTION);
462
        glLoadIdentity();
463
        glMatrixMode(GL_MODELVIEW);
464
        glLoadIdentity();
465
 
466
        // Call through to anyone else who needs to know about window sizing here.
467
}
468
 
469
static void beginOrtho2D(int xsize, int ysize) {
470
        glMatrixMode(GL_PROJECTION);
471
        glPushMatrix();
472
        glLoadIdentity();
473
        gluOrtho2D(0.0, xsize, 0.0, ysize);
474
        glMatrixMode(GL_MODELVIEW);
475
        glPushMatrix();
476
        glLoadIdentity();      
477
}
478
 
479
static void endOrtho2D(void) {
480
        glMatrixMode(GL_PROJECTION);
481
        glPopMatrix();
482
        glMatrixMode(GL_MODELVIEW);
483
        glPopMatrix();
484
}
485
 
486
static void Display(void)
487
{
488
        // Select correct buffer for this context.
489
        glDrawBuffer(GL_BACK);
490
        glClear(GL_COLOR_BUFFER_BIT);
491
    glDisable(GL_DEPTH_TEST);
492
        glDisable(GL_LIGHTING);
493
        glDisable(GL_TEXTURE_2D);
494
        beginOrtho2D(gXsize, gYsize);
495
 
496
    if (mode == 0) {
497
 
498
                arglDispImage(gARTImage, &gARTCparam, 1.0, gArglSettings);      // zoom = 1.0.
499
                arVideoCapNext();
500
                gARTImage = NULL;
501
 
502
    } else if (mode == 1) {
503
 
504
                arglDispImage(gSaveARTImage, &gARTCparam, 1.0, gSaveArglSettings);
505
 
506
        drawPrevLine();
507
        drawNextLine();
508
        }
509
 
510
        endOrtho2D();
511
    glutSwapBuffers();
512
}
513
 
514
static void drawPrevLine(void)
515
{
516
    int     i;
517
 
518
    glColor3f(0.0,0.0,1.0);
519
    for (i = 0; i < line_num_current; i++) {
520
        if (line_info[loop_num_current][i][0] == -1.0) continue;
521
        draw_warp_line(line_info[loop_num_current][i][0], line_info[loop_num_current][i][2],
522
                       line_info[loop_num_current][i][1], line_info[loop_num_current][i][3]);
523
    }
524
}
525
 
526
static void drawNextLine(void)
527
{
528
    double sin_theta, cos_theta;
529
    double x1, x2;
530
    double y1, y2;
531
 
532
    sin_theta = sin( (double)(theta*3.141592/180.0) );
533
    cos_theta = cos( (double)(theta*3.141592/180.0) );
534
 
535
    if (cos_theta != 0) {
536
        x1 = radius / cos_theta;
537
        x2 = (radius - (gYsize-1)*sin_theta) / cos_theta;
538
    } else {
539
        x1 = x2 = -1.0;
540
    }
541
 
542
    if (sin_theta != 0) {
543
        y1 = radius / sin_theta;
544
        y2 = (radius - (gXsize-1)*cos_theta) / sin_theta;
545
    } else {
546
        y1 = y2 = -1.0;
547
    }
548
 
549
    gEndY = -1;
550
    if (x1 >= 0 && x1 <= gXsize-1) {
551
         gStartX = x1;
552
         gStartY = 0;
553
         if (x2 >= 0 && x2 <= gXsize-1) {
554
             gEndX = x2;
555
             gEndY = gYsize-1;
556
         } else if (y1 >= 0 && y1 <= gYsize-1) {
557
             gEndX = 0;
558
             gEndY = y1;
559
         } else if (y2 >= 0 && y2 <= gYsize-1) {
560
             gEndX = gXsize-1;
561
             gEndY = y2;
562
         } else {
563
                         printf("???\n");
564
                 }
565
    } else if (y1 >= 0 && y1 <= gYsize-1) {
566
         gStartX = 0;
567
         gStartY = y1;
568
         if (x2 >= 0 && x2 <= gXsize-1) {
569
             gEndX = x2;
570
             gEndY = gYsize-1;
571
         } else if (y2 >= 0 && y2 <= gYsize-1) {
572
             gEndX = gXsize-1;
573
             gEndY = y2;
574
         } else {
575
                         printf("???\n");
576
                 }
577
    } else if (x2 >= 0 && x2 <= gXsize-1) {
578
         gStartX = x2;
579
         gStartY = gYsize-1;
580
         if (y2 >= 0 && y2 <= gYsize-1) {
581
             gEndX = gXsize-1;
582
             gEndY = y2;
583
         } else {
584
                         printf("???\n");
585
                 }
586
    }
587
 
588
    glColor3f(1.0,1.0,1.0);
589
    if (gEndY != -1) {
590
        draw_warp_line(gStartX, gEndX, gStartY, gEndY);
591
    }
592
}
593
 
594
static void draw_warp_line(double sx, double ex, double sy, double ey)
595
{
596
    double   a, b, c;
597
    double   x, y;
598
    double   x1, y1;
599
    int      i;
600
 
601
    a = ey - sy;
602
    b = sx - ex;
603
    c = sy*ex - sx*ey;
604
 
605
    glLineWidth(1.0f);
606
    glBegin(GL_LINE_STRIP);
607
    if (a*a >= b*b) {
608
        for (i = -20; i <= gYsize+20; i+=10) {
609
            x = -(b*i + c)/a;
610
            y = i;
611
 
612
            arParamIdeal2Observ(dist_factor, x, y, &x1, &y1);
613
            glVertex2f(x1, gYsize-1-y1);
614
        }
615
    } else {
616
        for (i = -20; i <= gXsize+20; i+=10) {
617
            x = i;
618
            y = -(a*i + c)/b;
619
 
620
            arParamIdeal2Observ(dist_factor, x, y, &x1, &y1);
621
            glVertex2f(x1, gYsize-1-y1);
622
        }
623
    }
624
    glEnd();
625
}
626
 
627
 
628
 
629
static void getCpara(void)
630
{
631
    double  *world_coord;
632
    double  *screen_coord;
633
    int     point_num;
634
    int     i, j, k;
635
 
636
    point_num = 0;
637
    for (k = 0; k < loop_num; k++) {
638
        for (i = 0; i < line_num; i++) {
639
            for (j = 0; j < line_num; j++) {
640
                if (inter_coord[k][i][j][0] != -10000.0) point_num++;
641
            }
642
        }
643
    }
644
        arMalloc(world_coord, double, point_num * 3);
645
        arMalloc(screen_coord, double, point_num * 2);
646
 
647
    point_num = 0;
648
    for (k = 0; k < loop_num; k++) {
649
        for (i = 0; i < line_num; i++) {
650
            if (line_info[k][i][0] == -1.0) continue;
651
            for (j = 0; j < line_num; j++) {
652
                if (line_info[k][j][0] == -1.0) continue;
653
                if (inter_coord[k][i][j][0] == -10000.0) continue;
654
 
655
                world_coord[point_num*3+0] = inter_coord[k][i][j][0];
656
                world_coord[point_num*3+1] = inter_coord[k][i][j][1];
657
                world_coord[point_num*3+2] = inter_coord[k][i][j][2];
658
                intersection(line_info[k][i], line_info[k][j],
659
                             &(screen_coord[point_num*2]));
660
 
661
                point_num++;
662
            }
663
        }
664
    }
665
    printf("point_num = %d\n", point_num);
666
    if (arParamGet((double (*)[3])world_coord, (double (*)[2])screen_coord, point_num, param.mat) < 0) {
667
        printf("ddd error!!\n");
668
        exit(0);
669
    }
670
 
671
    free(world_coord);
672
    free(screen_coord);
673
}
674
 
675
static void intersection(double line1[4], double line2[4], double *screen_coord)
676
{
677
    double a, b, c, d, e, f, g;
678
 
679
    a = line1[1] - line1[3];
680
    b = line1[2] - line1[0];
681
    c = line1[0] * a + line1[1] * b;
682
    d = line2[1] - line2[3];
683
    e = line2[2] - line2[0];
684
    f = line2[0] * d + line2[1] * e;
685
 
686
    g = a*e - b*d;
687
    if (g == 0.0) { printf("???\n"); exit(0); }
688
 
689
    screen_coord[0] = (c * e - b * f) / g;
690
    screen_coord[1] = (a * f - c * d) / g;
691
}