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/video.h>
43
#include <AR/param.h>
44
#include <AR/matrix.h>
45
#include <AR/gsub_lite.h>
46
#include "calib_camera.h"
47
 
48
// ============================================================================
49
//      Constants
50
// ============================================================================
51
 
52
#define CALIB_CAMERA2_DEBUG 0
53
 
54
// ============================================================================
55
//      Global variables
56
// ============================================================================
57
 
58
/* set up the video format globals */
59
 
60
#if defined(__sgi)
61
static char            *vconf = "-size=FULL";
62
#elif defined(__linux)
63
#  if defined(AR_INPUT_GSTREAMER)
64
char                    *vconf = "videotestsrc ! capsfilter caps=video/x-raw-rgb,bpp=24 ! identity name=artoolkit ! fakesink";
65
#  elif defined(AR_INPUT_V4L)
66
static char            *vconf = "-width=640 -height=480";
67
#  elif defined(AR_INPUT_1394CAM)
68
static char            *vconf = "-mode=640x480_YUV411";
69
#  elif defined(AR_INPUT_DV)
70
static char            *vconf = "";
71
#  endif
72
#elif defined(_WIN32)
73
static char                     *vconf = "Data\\WDM_camera_flipV.xml";
74
#elif defined(__APPLE__)
75
static char                     *vconf = "-width=640 -height=480";
76
#else
77
static 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
 
85
static int             gWin;
86
static int             gXsize = 0;
87
static int             gYsize = 0;
88
static int             gThresh = THRESH;
89
static unsigned char   *gClipImage = NULL;
90
 
91
static CALIB_PATT_T    gPatt;          
92
static double          dist_factor[4];
93
static double          mat[3][4];
94
 
95
static int             point_num;
96
static int             gDragStartX = -1, gDragStartY = -1, gDragEndX = -1, gDragEndY = -1;      // x and y coordinates of start and end of mouse drag.
97
 
98
static int             gStatus; // 0 = Waiting to grab image, 1 = Drawing bounding boxes, 2 = Placing warp lines.
99
static int             check_num;
100
 
101
// ============================================================================
102
//      Functions
103
// ============================================================================
104
 
105
int             main(int argc, char *argv[]);
106
static int      init(int argc, char *argv[]);
107
static void     Mouse(int button, int state, int x, int y);
108
static void     Motion(int x, int y);
109
static void     Keyboard(unsigned char key, int x, int y);
110
static void     Quit(void);
111
static void     Idle(void);
112
static void     Visibility(int visible);
113
static void     Reshape(int w, int h);
114
static void     Display(void);
115
static void     draw_warp_line(double a, double b , double c);
116
static void     draw_line(void);
117
static void     draw_line2(double *x, double *y, int num);
118
static void     draw_warp_line(double a, double b , double c);
119
static void     print_comment(int status);
120
static void     save_param(void);
121
 
122
int main(int argc, char *argv[])
123
{
124
        glutInit(&argc, argv);
125
    if (!init(argc, argv)) exit(-1);
126
 
127
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
128
    glutInitWindowSize(gXsize, gYsize);
129
    glutInitWindowPosition(100,100);
130
    gWin = glutCreateWindow("Calibrate camera parameters");
131
 
132
        // Setup argl library for current context.
133
        // Turn off distortion compensation.. we don't know distortion yet!
134
        if ((gArglSettings = arglSetupForCurrentContext()) == NULL) {
135
                fprintf(stderr, "main(): arglSetupForCurrentContext() returned error.\n");
136
                exit(-1);
137
        }
138
        arglDistortionCompensationSet(gArglSettings, FALSE);
139
 
140
        // Make a dummy camera parameter to supply when calling arglDispImage().
141
        gARTCparam.xsize = gXsize;
142
        gARTCparam.ysize = gYsize;
143
 
144
        // Register GLUT event-handling callbacks.
145
        // NB: Idle() is registered by Visibility.
146
    glutDisplayFunc(Display);
147
        glutReshapeFunc(Reshape);
148
        glutVisibilityFunc(Visibility);
149
        glutKeyboardFunc(Keyboard);
150
    glutMouseFunc(Mouse);
151
    glutMotionFunc(Motion);
152
 
153
        // Start grabbing.
154
        if (arVideoCapStart() != 0) {
155
        fprintf(stderr, "init(): Unable to begin camera data capture.\n");
156
                return (FALSE);        
157
        }
158
        point_num = 0;
159
    gStatus = 0;
160
    print_comment(0);
161
 
162
    glutMainLoop();
163
 
164
        return (0);
165
}
166
 
167
static int init(int argc, char *argv[])
168
{
169
    double  length;
170
    char    line[512];
171
    int     i, j;
172
 
173
    gPatt.h_num    = H_NUM;
174
    gPatt.v_num    = V_NUM;
175
    gPatt.loop_num = 0;
176
    if (gPatt.h_num < 3 || gPatt.v_num < 3) exit(0);
177
 
178
    printf("Input the distance between each marker dot, in millimeters: ");
179
    scanf("%lf", &length);
180
        while (getchar() != '\n');
181
 
182
    gPatt.world_coord = (CALIB_COORD_T *)malloc(sizeof(CALIB_COORD_T) * gPatt.h_num * gPatt.v_num);
183
    for (j = 0; j < gPatt.v_num; j++) {
184
        for (i = 0; i < gPatt.h_num; i++) {
185
            gPatt.world_coord[j*gPatt.h_num+i].x_coord = length * i;
186
            gPatt.world_coord[j*gPatt.h_num+i].y_coord = length * j;
187
        }
188
    }
189
 
190
        // Add command-line arguments to vconf string.
191
    strcpy(line, vconf);
192
    for (i = 1; i < argc; i++) {
193
        strcat(line, " ");
194
        strcat(line, argv[i]);
195
    }
196
 
197
        // Open the video path.
198
    if (arVideoOpen(line) < 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 clipping image (luminance only).
208
        arMalloc(gClipImage, unsigned char, gXsize * gYsize);
209
 
210
        return (TRUE);
211
}
212
 
213
static void grabImage(void) {
214
        ARUint8 *image;
215
 
216
        // Processing a new image.
217
        // Copy an image to saved image buffer.
218
        do {
219
                image = arVideoGetImage();
220
        } while (image == NULL);
221
        gPatt.loop_num++;
222
        if ((gPatt.arglSettings[gPatt.loop_num-1] = arglSetupForCurrentContext()) == NULL) {
223
                fprintf(stderr, "grabImage(): arglSetupForCurrentContext() returned error.\n");
224
                exit(-1);
225
        }
226
        arglDistortionCompensationSet(gPatt.arglSettings[gPatt.loop_num-1], FALSE);
227
        arMalloc((gPatt.savedImage)[gPatt.loop_num-1], unsigned char, gXsize*gYsize*AR_PIX_SIZE_DEFAULT);
228
        memcpy((gPatt.savedImage)[gPatt.loop_num-1], image, gXsize*gYsize*AR_PIX_SIZE_DEFAULT);
229
        printf("Grabbed image %d.\n", gPatt.loop_num);
230
        arMalloc(gPatt.point[gPatt.loop_num-1], CALIB_COORD_T, gPatt.h_num*gPatt.v_num);
231
}
232
 
233
static void ungrabImage(void) {
234
        if (gPatt.loop_num == 0) {printf("error!!\n"); exit(0);}
235
        free(gPatt.point[gPatt.loop_num-1]);
236
        gPatt.point[gPatt.loop_num-1] = NULL;
237
        free(gPatt.savedImage[gPatt.loop_num-1]);
238
        gPatt.savedImage[gPatt.loop_num-1] = NULL;
239
        arglCleanup(gPatt.arglSettings[gPatt.loop_num-1]);
240
        gPatt.loop_num--;                      
241
}
242
 
243
void checkFit(void) {
244
    printf("\n-----------\n");
245
        if (check_num < gPatt.loop_num) {
246
                printf("Checking fit on image %3d of %3d.\n", check_num + 1, gPatt.loop_num);
247
                if (check_num + 1 < gPatt.loop_num) {
248
                        printf("Press mouse button to check fit of next image.\n");
249
                } else {
250
                        printf("Press mouse button to calculate parameter.\n");
251
                }
252
                glutPostRedisplay();
253
        } else {
254
                if (gPatt.loop_num > 1) {
255
                        if (calc_inp(&gPatt, dist_factor, gXsize, gYsize, mat) < 0) {
256
                                printf("Calibration failed. Exiting.\n");
257
                                exit(0);
258
                        } else {
259
                                printf("Calibration succeeded. Enter filename to save camera parameter to below.\n");
260
                                save_param();
261
                        }
262
                } else {
263
                        printf("Not enough images to proceed with calibration. Exiting.\n");
264
                }
265
                Quit();
266
        }                              
267
}
268
 
269
static void eventCancel(void) {
270
        // What was cancelled?
271
        if (gStatus == 0) {
272
                // Cancelled grabbing.
273
                // Live video will not be needed from here on.
274
                arVideoCapStop();
275
                if (gPatt.loop_num == 0) {
276
                        // No images with all features identified, so quit.
277
                        Quit();
278
                } else {
279
                        // At least one image with all features identified,
280
                        // so calculate distortion.
281
                        calc_distortion(&gPatt, gXsize, gYsize, dist_factor);
282
                        printf("--------------\n");
283
                        printf("Center X: %f\n", dist_factor[0]);
284
                        printf("       Y: %f\n", dist_factor[1]);
285
                        printf("Dist Factor: %f\n", dist_factor[2]);
286
                        printf("Size Adjust: %f\n", dist_factor[3]);
287
                        printf("--------------\n");
288
                        // Distortion calculation done. Check fit.
289
                        gStatus = 2;
290
                        check_num = 0;
291
                        checkFit();
292
                }
293
        } else if (gStatus == 1) {
294
                // Cancelled rubber-bounding.
295
                ungrabImage();
296
                // Restart grabbing.
297
                point_num = 0;
298
                arVideoCapStart();
299
                gStatus = 0;
300
                if (gPatt.loop_num == 0) print_comment(0);
301
                else                     print_comment(4);     
302
        }
303
}
304
 
305
static void Mouse(int button, int state, int x, int y)
306
{
307
    unsigned char   *p;
308
    int             ssx, ssy, eex, eey;
309
    int             i, j, k;
310
 
311
        if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN) {
312
                eventCancel();
313
        } else if (button == GLUT_LEFT_BUTTON) {
314
                if (state == GLUT_DOWN) {
315
                        if (gStatus == 0 && gPatt.loop_num < LOOP_MAX) {
316
                                // End grabbing.
317
                                // Begin waiting for drag for rubber-bounding of a feature.
318
                                grabImage();
319
                                gDragStartX = gDragStartY = gDragEndX = gDragEndY = -1;
320
                                arVideoCapStop();
321
                                gStatus = 1;
322
                                print_comment(1);                              
323
                        } else if (gStatus == 1) {
324
                                if (point_num < gPatt.h_num*gPatt.v_num) {
325
                                        // Drag for rubber-bounding of a feature has begun.
326
                                        gDragStartX = gDragEndX = x;
327
                                        gDragStartY = gDragEndY = y;
328
                                } else {
329
                                        // Feature point locations have been accepted.
330
                                        printf("### Image no.%d ###\n", gPatt.loop_num);
331
                                        for( j = 0; j < gPatt.v_num; j++ ) {
332
                                                for( i = 0; i < gPatt.h_num; i++ ) {
333
                                                        printf("%2d, %2d: %6.2f, %6.2f\n", i+1, j+1,
334
                                                                   gPatt.point[gPatt.loop_num-1][j*gPatt.h_num+i].x_coord,
335
                                                                   gPatt.point[gPatt.loop_num-1][j*gPatt.h_num+i].y_coord);
336
                                                }
337
                                        }
338
                                        printf("\n\n");
339
                                        // Restart grabbing.
340
                                        point_num = 0;
341
                                        arVideoCapStart();
342
                                        gStatus = 0;
343
                                        if (gPatt.loop_num < LOOP_MAX) print_comment(4);
344
                                        else                           print_comment(5);
345
                                }
346
                        } else if (gStatus == 2) {
347
                                check_num++;
348
                                checkFit();
349
                        }
350
                } else if (state == GLUT_UP) {
351
                        if (gStatus == 1
352
                                 && gDragStartX != -1 && gDragStartY != -1
353
                                 && gDragEndX != -1 && gDragEndY != -1
354
                                 && point_num < gPatt.h_num*gPatt.v_num) {
355
                                // Drag for rubber-bounding of a feature has finished. Begin identification
356
                                // of center of white region in gClipImage.
357
                                if (gDragStartX < gDragEndX) { ssx = gDragStartX; eex = gDragEndX; }
358
                                else         { ssx = gDragEndX; eex = gDragStartX; }
359
                                if (gDragStartY < gDragEndY) { ssy = gDragStartY; eey = gDragEndY; }
360
                                else         { ssy = gDragEndY; eey = gDragStartY; }
361
 
362
                                gPatt.point[gPatt.loop_num-1][point_num].x_coord = 0.0;
363
                                gPatt.point[gPatt.loop_num-1][point_num].y_coord = 0.0;
364
                                p = gClipImage;
365
                                k = 0;
366
                                for (j = 0; j < (eey-ssy+1); j++) {
367
                                        for (i = 0; i < (eex-ssx+1); i++) {
368
                                                gPatt.point[gPatt.loop_num-1][point_num].x_coord += i * *p;
369
                                                gPatt.point[gPatt.loop_num-1][point_num].y_coord += j * *p;
370
                                                k += *p;
371
                                                p++;
372
                                        }
373
                                }
374
                                if (k != 0) {
375
                                        gPatt.point[gPatt.loop_num-1][point_num].x_coord /= k;
376
                                        gPatt.point[gPatt.loop_num-1][point_num].y_coord /= k;
377
                                        gPatt.point[gPatt.loop_num-1][point_num].x_coord += ssx;
378
                                        gPatt.point[gPatt.loop_num-1][point_num].y_coord += ssy;
379
                                        point_num++;
380
                                        printf("Marked feature position %3d of %3d\n", point_num, gPatt.h_num*gPatt.v_num);
381
                                        if (point_num == gPatt.h_num*gPatt.v_num) print_comment(2);
382
                                }
383
                                gDragStartX = gDragStartY = gDragEndX = gDragEndY = -1;
384
                                glutPostRedisplay();
385
                        }
386
                }
387
        }
388
}
389
 
390
static void Motion(int x, int y)
391
{
392
    unsigned char   *p, *p1;
393
    int             ssx, ssy, eex, eey;
394
    int             i, j;
395
 
396
        // During mouse drag.
397
    if (gStatus == 1 && gDragStartX != -1 && gDragStartY != -1) {
398
 
399
                // Set x,y of end of mouse drag region.
400
        gDragEndX = x;
401
        gDragEndY = y;
402
 
403
                // Check that start is above and to left of end.
404
                if (gDragStartX < gDragEndX) { ssx = gDragStartX; eex = gDragEndX; }
405
                else         { ssx = gDragEndX; eex = gDragStartX; }
406
                if (gDragStartY < gDragEndY) { ssy = gDragStartY; eey = gDragEndY; }
407
                else         { ssy = gDragEndY; eey = gDragStartY; }
408
 
409
                // Threshold clipping area, copy it into gClipImage.
410
        p1 = gClipImage;
411
        for (j = ssy; j <= eey; j++) {
412
            p = &(gPatt.savedImage[gPatt.loop_num-1][(j*gXsize+ssx)*AR_PIX_SIZE_DEFAULT]);
413
            for (i = ssx; i <= eex; i++) {
414
#if (AR_DEFAULT_PIXEL_FORMAT == AR_PIXEL_FORMAT_BGRA)
415
                *p1 = (((255*3 - (*(p+0) + *(p+1) + *(p+2))) / 3) < gThresh ? 0 : 255);
416
#elif (AR_DEFAULT_PIXEL_FORMAT == AR_PIXEL_FORMAT_ABGR)
417
                *p1 = (((255*3 - (*(p+1) + *(p+2) + *(p+3))) / 3) < gThresh ? 0 : 255);
418
#elif (AR_DEFAULT_PIXEL_FORMAT == AR_PIXEL_FORMAT_ARGB)
419
                *p1 = (((255*3 - (*(p+1) + *(p+2) + *(p+3))) / 3) < gThresh ? 0 : 255);
420
#elif (AR_DEFAULT_PIXEL_FORMAT == AR_PIXEL_FORMAT_BGR)
421
                *p1 = (((255*3 - (*(p+0) + *(p+1) + *(p+2))) / 3) < gThresh ? 0 : 255);
422
#elif (AR_DEFAULT_PIXEL_FORMAT == AR_PIXEL_FORMAT_RGBA)
423
                *p1 = (((255*3 - (*(p+0) + *(p+1) + *(p+2))) / 3) < gThresh ? 0 : 255);
424
#elif (AR_DEFAULT_PIXEL_FORMAT == AR_PIXEL_FORMAT_RGB)
425
                *p1 = (((255*3 - (*(p+0) + *(p+1) + *(p+2))) / 3) < gThresh ? 0 : 255);
426
#elif (AR_DEFAULT_PIXEL_FORMAT == AR_PIXEL_FORMAT_2vuy)
427
                *p1 = ((255 - *(p+1)) < gThresh ? 0 : 255);
428
#elif (AR_DEFAULT_PIXEL_FORMAT == AR_PIXEL_FORMAT_yuvs)
429
                *p1 = ((255 - *(p+0)) < gThresh ? 0 : 255);
430
#elif (AR_DEFAULT_PIXEL_FORMAT == AR_PIXEL_FORMAT_MONO)
431
                *p1 = ((255 - *(p)) < gThresh ? 0 : 255);
432
#else
433
#  error Unknown default pixel format defined in config.h
434
#endif
435
                p  += AR_PIX_SIZE_DEFAULT;
436
                p1++;
437
            }
438
        }
439
                // Tell GLUT the display has changed.
440
                glutPostRedisplay();
441
    }
442
}
443
 
444
static void Keyboard(unsigned char key, int x, int y)
445
{
446
        switch (key) {
447
                case 0x1B:
448
                        eventCancel();
449
                        break;
450
                case 'T':
451
                case 't':
452
                        printf("Enter new threshold value (now = %d): ", gThresh);
453
                        scanf("%d",&gThresh); while( getchar()!='\n' );
454
                        printf("\n");
455
                        break;
456
                case '1':
457
                        gThresh -= 5;
458
                        if (gThresh < 0) gThresh = 0;
459
                        break;
460
                case '2':
461
                        gThresh += 5;
462
                        if (gThresh > 255) gThresh = 255;
463
                        break;
464
                default:
465
                        break;
466
        }
467
}
468
 
469
static void Quit(void)
470
{
471
        if (gClipImage) {
472
                free(gClipImage);
473
                gClipImage = NULL;
474
        }
475
        if (gArglSettings) arglCleanup(gArglSettings);
476
        if (gWin) glutDestroyWindow(gWin);
477
        arVideoClose();
478
        exit(0);
479
}
480
 
481
static void Idle(void)
482
{
483
        static int ms_prev;
484
        int ms;
485
        float s_elapsed;
486
        ARUint8 *image;
487
 
488
        // Find out how long since Idle() last ran.
489
        ms = glutGet(GLUT_ELAPSED_TIME);
490
        s_elapsed = (float)(ms - ms_prev) * 0.001;
491
        if (s_elapsed < 0.01f) return; // Don't update more often than 100 Hz.
492
        ms_prev = ms;
493
 
494
        // Grab a video frame.
495
        if (gStatus == 0) {
496
                if ((image = arVideoGetImage()) != NULL) {
497
                        gARTImage = image;
498
                        // Tell GLUT the display has changed.
499
                        glutPostRedisplay();
500
                }      
501
        }
502
}
503
 
504
//
505
//      This function is called on events when the visibility of the
506
//      GLUT window changes (including when it first becomes visible).
507
//
508
static void Visibility(int visible)
509
{
510
        if (visible == GLUT_VISIBLE) {
511
                glutIdleFunc(Idle);
512
        } else {
513
                glutIdleFunc(NULL);
514
        }
515
}
516
 
517
//
518
//      This function is called when the
519
//      GLUT window is resized.
520
//
521
static void Reshape(int w, int h)
522
{
523
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
524
        glViewport(0, 0, (GLsizei) w, (GLsizei) h);
525
 
526
        glMatrixMode(GL_PROJECTION);
527
        glLoadIdentity();
528
        glMatrixMode(GL_MODELVIEW);
529
        glLoadIdentity();
530
 
531
        // Call through to anyone else who needs to know about window sizing here.
532
}
533
 
534
static void beginOrtho2D(int xsize, int ysize) {
535
        glMatrixMode(GL_PROJECTION);
536
        glPushMatrix();
537
        glLoadIdentity();
538
        gluOrtho2D(0.0, xsize, 0.0, ysize);
539
        glMatrixMode(GL_MODELVIEW);
540
        glPushMatrix();
541
        glLoadIdentity();      
542
}
543
 
544
static void endOrtho2D(void) {
545
        glMatrixMode(GL_PROJECTION);
546
        glPopMatrix();
547
        glMatrixMode(GL_MODELVIEW);
548
        glPopMatrix();
549
}
550
 
551
static void Display(void)
552
{
553
    double         x, y;
554
    int            ssx, eex, ssy, eey;
555
    int            i;
556
 
557
        // Select correct buffer for this context.
558
        glDrawBuffer(GL_BACK);
559
        glClear(GL_COLOR_BUFFER_BIT);
560
    glDisable(GL_DEPTH_TEST);
561
        glDisable(GL_LIGHTING);
562
        glDisable(GL_TEXTURE_2D);
563
        beginOrtho2D(gXsize, gYsize);
564
 
565
    if (gStatus == 0) {
566
 
567
                arglDispImage(gARTImage, &gARTCparam, 1.0, gArglSettings);      // zoom = 1.0.
568
                arVideoCapNext();
569
                gARTImage = NULL;
570
 
571
    } else if (gStatus == 1) {
572
 
573
        arglDispImage(gPatt.savedImage[gPatt.loop_num-1], &gARTCparam, 1.0, gPatt.arglSettings[gPatt.loop_num-1]);
574
                // Draw red crosses on the points in the image.
575
        for (i = 0; i < point_num; i++) {
576
            x = gPatt.point[gPatt.loop_num-1][i].x_coord;
577
            y = gPatt.point[gPatt.loop_num-1][i].y_coord;
578
            glColor3f(1.0f, 0.0f, 0.0f);
579
            glBegin(GL_LINES);
580
              glVertex2d(x-10.0, (GLdouble)(gYsize-1)-y);
581
              glVertex2d(x+10.0, (GLdouble)(gYsize-1)-y);
582
              glVertex2d(x, (GLdouble)(gYsize-1)-(y-10.0));
583
              glVertex2d(x, (GLdouble)(gYsize-1)-(y+10.0));
584
            glEnd();
585
        }
586
 
587
                // Draw the current mouse drag clipping area.
588
        if (gDragStartX != -1 && gDragStartY != -1
589
                        && gDragEndX != -1 && gDragEndY != -1) {
590
                        if (gDragStartX < gDragEndX) { ssx = gDragStartX; eex = gDragEndX; }
591
                        else         { ssx = gDragEndX; eex = gDragStartX; }
592
                        if (gDragStartY < gDragEndY) { ssy = gDragStartY; eey = gDragEndY; }
593
                        else         { ssy = gDragEndY; eey = gDragStartY; }
594
#if 1
595
                        if (gClipImage) {
596
                                glPixelZoom(1.0f, -1.0f);       // ARToolKit bitmap 0.0 is at upper-left, OpenGL bitmap 0.0 is at lower-left.
597
                                glRasterPos2f((GLfloat)(ssx), (GLfloat)(gYsize-1-ssy));
598
                                glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
599
                                glDrawPixels(eex-ssx+1, eey-ssy+1, GL_LUMINANCE, GL_UNSIGNED_BYTE, gClipImage);
600
                        }
601
#else
602
            glColor3f(0.0f, 0.0f, 1.0f);
603
            glBegin(GL_LINE_LOOP);
604
              glVertex2i(gDragStartX, (gYsize-1)-gDragStartY);
605
              glVertex2i(gDragEndX, (gYsize-1)-gDragStartY);
606
              glVertex2i(gDragEndX, (gYsize-1)-gDragEndY);
607
              glVertex2i(gDragStartX, (gYsize-1)-gDragEndY);
608
            glEnd();
609
#endif
610
        }
611
 
612
    } else if (gStatus == 2) {
613
 
614
        arglDispImage(gPatt.savedImage[check_num], &gARTCparam, 1.0, gPatt.arglSettings[check_num]);
615
        for (i = 0; i < gPatt.h_num*gPatt.v_num; i++) {
616
            x = gPatt.point[check_num][i].x_coord;
617
            y = gPatt.point[check_num][i].y_coord;
618
            glColor3f(1.0f, 0.0f, 0.0f);
619
            glBegin(GL_LINES);
620
                        glVertex2d(x-10.0, (GLdouble)(gYsize-1)-y);
621
                        glVertex2d(x+10.0, (GLdouble)(gYsize-1)-y);
622
                        glVertex2d(x, (GLdouble)(gYsize-1)-(y-10.0));
623
                        glVertex2d(x, (GLdouble)(gYsize-1)-(y+10.0));
624
            glEnd();
625
        }
626
        draw_line();
627
 
628
    }
629
 
630
        endOrtho2D();
631
    glutSwapBuffers();
632
}
633
 
634
static void draw_line(void)
635
{
636
    double   *x, *y;
637
    int      max;
638
    // int      num; // unreferenced
639
    int      i, j, k, l;
640
    int      p;
641
 
642
    max = (gPatt.v_num > gPatt.h_num) ? gPatt.v_num : gPatt.h_num;
643
    arMalloc(x, double, max);
644
    arMalloc(y, double, max);
645
 
646
    i = check_num;
647
 
648
    for (j = 0; j < gPatt.v_num; j++) {
649
        for (k = 0; k < gPatt.h_num; k++) {
650
            x[k] = gPatt.point[i][j*gPatt.h_num+k].x_coord;
651
            y[k] = gPatt.point[i][j*gPatt.h_num+k].y_coord;
652
        }
653
        draw_line2(x, y, gPatt.h_num);
654
    }
655
 
656
    for (j = 0; j < gPatt.h_num; j++) {
657
        for (k = 0; k < gPatt.v_num; k++) {
658
            x[k] = gPatt.point[i][k*gPatt.h_num+j].x_coord;
659
            y[k] = gPatt.point[i][k*gPatt.h_num+j].y_coord;
660
        }
661
        draw_line2(x, y, gPatt.v_num);
662
    }
663
 
664
    for (j = 3 - gPatt.v_num; j < gPatt.h_num - 2; j++) {
665
        p = 0;
666
        for (k = 0; k < gPatt.v_num; k++) {
667
            l = j+k;
668
            if (l < 0 || l >= gPatt.h_num) continue;
669
            x[p] = gPatt.point[i][k*gPatt.h_num+l].x_coord;
670
            y[p] = gPatt.point[i][k*gPatt.h_num+l].y_coord;
671
            p++;
672
        }
673
        draw_line2(x, y, p);
674
    }
675
 
676
    for (j = 2; j < gPatt.h_num + gPatt.v_num - 3; j++) {
677
        p = 0;
678
        for (k = 0; k < gPatt.v_num; k++) {
679
            l = j-k;
680
            if (l < 0 || l >= gPatt.h_num) continue;
681
            x[p] = gPatt.point[i][k*gPatt.h_num+l].x_coord;
682
            y[p] = gPatt.point[i][k*gPatt.h_num+l].y_coord;
683
            p++;
684
        }
685
        draw_line2(x, y, p);
686
    }
687
 
688
    free(x);
689
    free(y);
690
}
691
 
692
static void draw_line2( double *x, double *y, int num )
693
{
694
    ARMat    *input, *evec;
695
    ARVec    *ev, *mean;
696
    double   a, b, c;
697
    int      i;
698
 
699
    ev     = arVecAlloc(2);
700
    mean   = arVecAlloc(2);
701
    evec   = arMatrixAlloc(2, 2);
702
 
703
    input  = arMatrixAlloc(num, 2);
704
    for (i = 0; i < num; i++) {
705
        arParamObserv2Ideal(dist_factor, x[i], y[i],
706
                             &(input->m[i*2+0]), &(input->m[i*2+1]));
707
    }
708
    if (arMatrixPCA(input, evec, ev, mean) < 0) exit(0);
709
    a =  evec->m[1];
710
    b = -evec->m[0];
711
    c = -(a*mean->v[0] + b*mean->v[1]);
712
 
713
    arMatrixFree(input);
714
    arMatrixFree(evec);
715
    arVecFree(mean);
716
    arVecFree(ev);
717
 
718
    draw_warp_line(a, b, c);
719
}
720
 
721
static void draw_warp_line(double a, double b , double c)
722
{
723
    double   x, y;
724
    double   x1, y1;
725
    int      i;
726
 
727
    glLineWidth(1.0f);
728
    glBegin(GL_LINE_STRIP);
729
    if (a*a >= b*b) {
730
        for (i = -20; i <= gYsize+20; i+=10) {
731
            x = -(b*i + c)/a;
732
            y = i;
733
 
734
            arParamIdeal2Observ(dist_factor, x, y, &x1, &y1);
735
            glVertex2f(x1, gYsize-1-y1);
736
        }
737
    } else {
738
        for(i = -20; i <= gXsize+20; i+=10) {
739
            x = i;
740
            y = -(a*i + c)/b;
741
 
742
            arParamIdeal2Observ(dist_factor, x, y, &x1, &y1);
743
            glVertex2f(x1, gYsize-1-y1);
744
        }
745
    }
746
    glEnd();
747
}
748
 
749
static void print_comment(int status)
750
{
751
    printf("\n-----------\n");
752
    switch(status) {
753
        case 0:
754
                        printf("Press mouse button to grab first image,\n");
755
                        printf("or press right mouse button or [esc] to quit.\n");
756
                        break;
757
        case 1:
758
                        printf("Press mouse button and drag mouse to rubber-bound features (%d x %d),\n", gPatt.h_num, gPatt.v_num);
759
                        printf("or press right mouse button or [esc] to cancel rubber-bounding & retry grabbing.\n");
760
                        break;
761
        case 2:
762
                        printf("Press mouse button to save feature positions,\n");
763
                        printf("or press right mouse button or [esc] to discard feature positions & retry grabbing.\n");
764
                        break;
765
        case 4:
766
                        printf("Press mouse button to grab next image,\n");
767
                        printf("or press right mouse button or [esc] to calculate distortion parameter.\n");
768
                        break;
769
        case 5:
770
                        printf("Press right mouse button or [esc] to calculate distortion parameter.\n");
771
                        break;
772
    }
773
}
774
 
775
static void save_param(void)
776
{
777
    char     name[256];
778
    ARParam  param;
779
    int      i, j;
780
 
781
    param.xsize = gXsize;
782
    param.ysize = gYsize;
783
    for (i = 0; i < 4; i++) param.dist_factor[i] = dist_factor[i];
784
    for (j = 0; j < 3; j++) {
785
        for (i = 0; i < 4; i++) {
786
            param.mat[j][i] = mat[j][i];
787
        }
788
    }
789
    arParamDisp( &param );
790
 
791
    printf("Filename: ");
792
    scanf( "%s", name );
793
    arParamSave( name, 1, &param );
794
 
795
    return;
796
}
797