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