00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifdef _WIN32
00026 # include <windows.h>
00027 #endif
00028 #include <math.h>
00029 #include <stdio.h>
00030 #include <stdlib.h>
00031 #include <string.h>
00032 #ifndef __APPLE__
00033 # include <GL/glut.h>
00034 # ifdef GL_VERSION_1_2
00035 # include <GL/glext.h>
00036 # endif
00037 #else
00038 # include <GLUT/glut.h>
00039 # include <OpenGL/glext.h>
00040 #endif
00041 #include <AR/config.h>
00042 #include <AR/ar.h>
00043 #include <AR/video.h>
00044 #include <AR/param.h>
00045 #include <AR/gsub_lite.h>
00046 #include "calib_cparam.h"
00047
00048
00049
00050
00051
00052 #define CALIB_CPARAM_DEBUG 0
00053
00054
00055
00056
00057
00058
00059
00060 #if defined(__sgi)
00061 char *vconf = "-size=FULL";
00062 #elif defined(__linux)
00063 # if defined(AR_INPUT_GSTREAMER)
00064 char *vconf = "videotestsrc";
00065 # elif defined(AR_INPUT_V4L)
00066 char *vconf = "-width=640 -height=480";
00067 # elif defined(AR_INPUT_1394CAM)
00068 char *vconf = "-mode=640x480_YUV411";
00069 # elif defined(AR_INPUT_DV)
00070 char *vconf = "";
00071 # endif
00072 #elif defined(_WIN32)
00073 char *vconf = "Data\\WDM_camera_flipV.xml";
00074 #elif defined(__APPLE__)
00075 char *vconf = "-width=640 -height=480";
00076 #else
00077 char *vconf = "";
00078 #endif
00079
00080 static ARUint8 *gARTImage = NULL;
00081 static ARParam gARTCparam;
00082 static ARGL_CONTEXT_SETTINGS_REF gArglSettings = NULL;
00083
00084 static int gWin;
00085 static int gXsize = 0;
00086 static int gYsize = 0;
00087 int refresh;
00088
00089 static unsigned char *gSaveARTImage = NULL;
00090 static ARGL_CONTEXT_SETTINGS_REF gSaveArglSettings = NULL;
00091
00092 static ARParam param;
00093 static double dist_factor[4];
00094
00095 int line_num;
00096 int loop_num;
00097 int line_mode[LINE_MAX];
00098 double inter_coord[LOOP_MAX][LINE_MAX][LINE_MAX][3];
00099 double line_info[LOOP_MAX][LINE_MAX][4];
00100
00101 int mode;
00102 int line_num_current;
00103 int loop_num_current;
00104 double theta;
00105 double radius;
00106 double gStartX, gStartY, gEndX, gEndY;
00107
00108
00109
00110
00111
00112 int main(int argc, char *argv[]);
00113 static int init(int argc, char *argv[]);
00114 static void Keyboard(unsigned char key, int x, int y);
00115 static void Special(int key, int x, int y);
00116 static void Mouse(int button, int state, int x, int y);
00117 static void Quit(void);
00118 static void Idle(void);
00119 static void Visibility(int visible);
00120 static void Reshape(int w, int h);
00121 static void Display(void);
00122 static void drawPrevLine(void);
00123 static void drawNextLine(void);
00124 static void draw_warp_line(double sx, double ex, double sy, double ey);
00125 static void getCpara(void);
00126 static void intersection( double line1[4], double line2[4], double *screen_coord );
00127
00128
00129 int main(int argc, char *argv[])
00130 {
00131 glutInit(&argc, argv);
00132 if (!init(argc, argv)) exit(-1);
00133
00134 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
00135 glutInitWindowSize(gXsize, gYsize);
00136 glutInitWindowPosition(100,100);
00137 gWin = glutCreateWindow("Camera calibration");
00138
00139
00140
00141 if ((gArglSettings = arglSetupForCurrentContext()) == NULL) {
00142 fprintf(stderr, "main(): arglSetupForCurrentContext() returned error.\n");
00143 exit(-1);
00144 }
00145 arglDistortionCompensationSet(gArglSettings, FALSE);
00146
00147
00148 gARTCparam.xsize = gXsize;
00149 gARTCparam.ysize = gYsize;
00150
00151
00152 if ((gSaveArglSettings = arglSetupForCurrentContext()) == NULL) {
00153 fprintf(stderr, "grabImage(): arglSetupForCurrentContext() returned error.\n");
00154 exit(-1);
00155 }
00156 arglDistortionCompensationSet(gSaveArglSettings, FALSE);
00157 arMalloc(gSaveARTImage, unsigned char, gXsize*gYsize*AR_PIX_SIZE_DEFAULT);
00158
00159
00160
00161 glutDisplayFunc(Display);
00162 glutReshapeFunc(Reshape);
00163 glutVisibilityFunc(Visibility);
00164 glutKeyboardFunc(Keyboard);
00165 glutSpecialFunc(Special);
00166 glutMouseFunc(Mouse);
00167
00168 if (arVideoCapStart() != 0) {
00169 fprintf(stderr, "init(): Unable to begin camera data capture.\n");
00170 return (FALSE);
00171 }
00172 mode = 0;
00173 line_num_current = 0;
00174 loop_num_current = 0;
00175
00176 glutMainLoop();
00177 return (0);
00178 }
00179
00180 static int init(int argc, char *argv[])
00181 {
00182 printf("Input center coordinates: X = ");
00183 scanf("%lf", &dist_factor[0]);
00184 while (getchar() != '\n');
00185 printf(" : Y = ");
00186 scanf("%lf", &dist_factor[1]);
00187 while (getchar() != '\n');
00188 printf("Input distortion ratio: F = ");
00189 scanf("%lf", &dist_factor[2]);
00190 while (getchar() != '\n');
00191 printf("Input size adjustment factor: S = ");
00192 scanf("%lf", &dist_factor[3]);
00193 while (getchar() != '\n');
00194
00195 initLineModel(&line_num, &loop_num, line_mode, inter_coord);
00196
00197
00198 if (arVideoOpen(vconf) < 0) {
00199 fprintf(stderr, "init(): Unable to open connection to camera.\n");
00200 return (FALSE);
00201 }
00202
00203
00204 if (arVideoInqSize(&gXsize, &gYsize) < 0) return (FALSE);
00205 fprintf(stdout, "Camera image size (x,y) = (%d,%d)\n", gXsize, gYsize);
00206
00207
00208 arMalloc(gSaveARTImage, unsigned char, gXsize * gYsize * AR_PIX_SIZE_DEFAULT);
00209
00210 param.xsize = gXsize;
00211 param.ysize = gYsize;
00212 param.dist_factor[0] = dist_factor[0];
00213 param.dist_factor[1] = dist_factor[1];
00214 param.dist_factor[2] = dist_factor[2];
00215 param.dist_factor[3] = dist_factor[3];
00216
00217 return (TRUE);
00218 }
00219
00220 static void thetaRadiusSet(void) {
00221 if (line_num_current == 0) {
00222 if (line_mode[line_num_current] == L_HORIZONTAL) {
00223 theta = 90;
00224 radius = gYsize/2;
00225 } else {
00226 theta = 0;
00227 radius = gXsize/2;
00228 }
00229 } else {
00230 if (line_mode[line_num_current] == L_HORIZONTAL) {
00231 if (line_mode[line_num_current] == line_mode[line_num_current-1]) {
00232 radius += 10.0;
00233 } else {
00234 theta = 90;
00235 radius = gYsize/2;
00236 }
00237 } else {
00238 if (line_mode[line_num_current] == line_mode[line_num_current-1]) {
00239 radius += 10.0;
00240 } else {
00241 theta = 0;
00242 radius = gXsize/2;
00243 }
00244 }
00245 }
00246 }
00247
00248 static void eventCancel(void) {
00249 if (mode == 0) {
00250
00251 arVideoCapStop();
00252 Quit();
00253 } else if (mode == 1) {
00254 if (line_num_current == 0) {
00255
00256 arVideoCapStart();
00257 mode = 0;
00258 } else {
00259
00260 line_num_current = 0;
00261 thetaRadiusSet();
00262 glutPostRedisplay();
00263 }
00264 }
00265 }
00266
00267 static void Mouse(int button, int state, int x, int y)
00268 {
00269 ARUint8 *image;
00270
00271 if (state == GLUT_DOWN) {
00272 if (button == GLUT_RIGHT_BUTTON) {
00273 eventCancel();
00274 } else if (button == GLUT_LEFT_BUTTON && mode == 0) {
00275
00276
00277 do {
00278 image = arVideoGetImage();
00279 } while (image == NULL);
00280 memcpy(gSaveARTImage, image, gXsize*gYsize*AR_PIX_SIZE_DEFAULT);
00281 printf("Grabbed image.\n");
00282 arVideoCapStop();
00283 mode = 1;
00284 line_num_current = 0;
00285 thetaRadiusSet();
00286 glutPostRedisplay();
00287 }
00288 }
00289 }
00290
00291 static void Keyboard(unsigned char key, int x, int y)
00292 {
00293 ARParam iparam;
00294 double trans[3][4];
00295 char name[256];
00296 int k = 1;
00297
00298 if( mode == 0 ) return;
00299
00300 switch( key ) {
00301 case 0x1B:
00302 gStartX = -1.0;
00303 gStartY = -1.0;
00304 gEndX = -1.0;
00305 gEndY = -1.0;
00306
00307 case 0x0D:
00308 line_info[loop_num_current][line_num_current][0] = gStartX;
00309 line_info[loop_num_current][line_num_current][1] = gStartY;
00310 line_info[loop_num_current][line_num_current][2] = gEndX;
00311 line_info[loop_num_current][line_num_current][3] = gEndY;
00312 line_num_current++;
00313 if (line_num_current < line_num) {
00314 thetaRadiusSet();
00315 } else {
00316
00317 loop_num_current++;
00318 if (loop_num_current < loop_num) {
00319 arVideoCapStart();
00320 mode = 0;
00321 } else {
00322
00323 getCpara();
00324 arParamDecomp( ¶m, &iparam, trans );
00325 arParamDisp( &iparam );
00326
00327 printf("Input filename: ");
00328 scanf("%s", name);
00329 arParamSave( name, 1, &iparam );
00330
00331 Quit();
00332 }
00333 }
00334 break;
00335 default:
00336 k = 0;
00337 break;
00338 }
00339 if (k) glutPostRedisplay();
00340 }
00341
00342
00343 static void Special(int key, int x, int y)
00344 {
00345 double mx, my;
00346 int k = 1;
00347
00348 if (mode == 0) return;
00349
00350 if (line_mode[line_num_current] == L_HORIZONTAL) {
00351 switch (key) {
00352 case GLUT_KEY_UP:
00353 radius -= 1.0;
00354 break;
00355 case GLUT_KEY_DOWN:
00356 radius += 1.0;
00357 break;
00358 case GLUT_KEY_LEFT:
00359 mx = (gStartX + gEndX)/ 2.0;
00360 my = (gStartY + gEndY)/ 2.0;
00361 theta -= 0.25;
00362 radius = cos( (double)(theta*3.141592/180.0) ) * mx
00363 + sin( (double)(theta*3.141592/180.0) ) * my;
00364 break;
00365 case GLUT_KEY_RIGHT:
00366 mx = (gStartX + gEndX)/ 2.0;
00367 my = (gStartY + gEndY)/ 2.0;
00368 theta += 0.25;
00369 radius = cos( (double)(theta*3.141592/180.0) ) * mx
00370 + sin( (double)(theta*3.141592/180.0) ) * my;
00371 break;
00372 default:
00373 k = 0;
00374 break;
00375 }
00376 } else {
00377 switch (key) {
00378 case GLUT_KEY_UP:
00379 mx = (gStartX + gEndX)/ 2.0;
00380 my = (gStartY + gEndY)/ 2.0;
00381 theta += 0.25;
00382 radius = cos( (double)(theta*3.141592/180.0) ) * mx
00383 + sin( (double)(theta*3.141592/180.0) ) * my;
00384 break;
00385 case GLUT_KEY_DOWN:
00386 mx = (gStartX + gEndX)/ 2.0;
00387 my = (gStartY + gEndY)/ 2.0;
00388 theta -= 0.25;
00389 radius = cos( (double)(theta*3.141592/180.0) ) * mx
00390 + sin( (double)(theta*3.141592/180.0) ) * my;
00391 break;
00392 case GLUT_KEY_LEFT:
00393 radius -= 1.0;
00394 break;
00395 case GLUT_KEY_RIGHT:
00396 radius += 1.0;
00397 break;
00398 default:
00399 k = 0;
00400 break;
00401 }
00402 }
00403
00404 if (k) glutPostRedisplay();
00405 }
00406
00407 static void Quit(void)
00408 {
00409 if (gSaveArglSettings) arglCleanup(gSaveArglSettings);
00410 if (gArglSettings) arglCleanup(gArglSettings);
00411 if (gWin) glutDestroyWindow(gWin);
00412 arVideoClose();
00413 exit(0);
00414 }
00415
00416 static void Idle(void)
00417 {
00418 static int ms_prev;
00419 int ms;
00420 float s_elapsed;
00421 ARUint8 *image;
00422
00423
00424 ms = glutGet(GLUT_ELAPSED_TIME);
00425 s_elapsed = (float)(ms - ms_prev) * 0.001;
00426 if (s_elapsed < 0.01f) return;
00427 ms_prev = ms;
00428
00429
00430 if (mode == 0) {
00431 if ((image = arVideoGetImage()) != NULL) {
00432 gARTImage = image;
00433
00434 glutPostRedisplay();
00435 }
00436 }
00437 }
00438
00439
00440
00441
00442
00443 static void Visibility(int visible)
00444 {
00445 if (visible == GLUT_VISIBLE) {
00446 glutIdleFunc(Idle);
00447 } else {
00448 glutIdleFunc(NULL);
00449 }
00450 }
00451
00452
00453
00454
00455
00456 static void Reshape(int w, int h)
00457 {
00458 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00459 glViewport(0, 0, (GLsizei) w, (GLsizei) h);
00460
00461 glMatrixMode(GL_PROJECTION);
00462 glLoadIdentity();
00463 glMatrixMode(GL_MODELVIEW);
00464 glLoadIdentity();
00465
00466
00467 }
00468
00469 static void beginOrtho2D(int xsize, int ysize) {
00470 glMatrixMode(GL_PROJECTION);
00471 glPushMatrix();
00472 glLoadIdentity();
00473 gluOrtho2D(0.0, xsize, 0.0, ysize);
00474 glMatrixMode(GL_MODELVIEW);
00475 glPushMatrix();
00476 glLoadIdentity();
00477 }
00478
00479 static void endOrtho2D(void) {
00480 glMatrixMode(GL_PROJECTION);
00481 glPopMatrix();
00482 glMatrixMode(GL_MODELVIEW);
00483 glPopMatrix();
00484 }
00485
00486 static void Display(void)
00487 {
00488
00489 glDrawBuffer(GL_BACK);
00490 glClear(GL_COLOR_BUFFER_BIT);
00491 glDisable(GL_DEPTH_TEST);
00492 glDisable(GL_LIGHTING);
00493 glDisable(GL_TEXTURE_2D);
00494 beginOrtho2D(gXsize, gYsize);
00495
00496 if (mode == 0) {
00497
00498 arglDispImage(gARTImage, &gARTCparam, 1.0, gArglSettings);
00499 arVideoCapNext();
00500 gARTImage = NULL;
00501
00502 } else if (mode == 1) {
00503
00504 arglDispImage(gSaveARTImage, &gARTCparam, 1.0, gSaveArglSettings);
00505
00506 drawPrevLine();
00507 drawNextLine();
00508 }
00509
00510 endOrtho2D();
00511 glutSwapBuffers();
00512 }
00513
00514 static void drawPrevLine(void)
00515 {
00516 int i;
00517
00518 glColor3f(0.0,0.0,1.0);
00519 for (i = 0; i < line_num_current; i++) {
00520 if (line_info[loop_num_current][i][0] == -1.0) continue;
00521 draw_warp_line(line_info[loop_num_current][i][0], line_info[loop_num_current][i][2],
00522 line_info[loop_num_current][i][1], line_info[loop_num_current][i][3]);
00523 }
00524 }
00525
00526 static void drawNextLine(void)
00527 {
00528 double sin_theta, cos_theta;
00529 double x1, x2;
00530 double y1, y2;
00531
00532 sin_theta = sin( (double)(theta*3.141592/180.0) );
00533 cos_theta = cos( (double)(theta*3.141592/180.0) );
00534
00535 if (cos_theta != 0) {
00536 x1 = radius / cos_theta;
00537 x2 = (radius - (gYsize-1)*sin_theta) / cos_theta;
00538 } else {
00539 x1 = x2 = -1.0;
00540 }
00541
00542 if (sin_theta != 0) {
00543 y1 = radius / sin_theta;
00544 y2 = (radius - (gXsize-1)*cos_theta) / sin_theta;
00545 } else {
00546 y1 = y2 = -1.0;
00547 }
00548
00549 gEndY = -1;
00550 if (x1 >= 0 && x1 <= gXsize-1) {
00551 gStartX = x1;
00552 gStartY = 0;
00553 if (x2 >= 0 && x2 <= gXsize-1) {
00554 gEndX = x2;
00555 gEndY = gYsize-1;
00556 } else if (y1 >= 0 && y1 <= gYsize-1) {
00557 gEndX = 0;
00558 gEndY = y1;
00559 } else if (y2 >= 0 && y2 <= gYsize-1) {
00560 gEndX = gXsize-1;
00561 gEndY = y2;
00562 } else {
00563 printf("???\n");
00564 }
00565 } else if (y1 >= 0 && y1 <= gYsize-1) {
00566 gStartX = 0;
00567 gStartY = y1;
00568 if (x2 >= 0 && x2 <= gXsize-1) {
00569 gEndX = x2;
00570 gEndY = gYsize-1;
00571 } else if (y2 >= 0 && y2 <= gYsize-1) {
00572 gEndX = gXsize-1;
00573 gEndY = y2;
00574 } else {
00575 printf("???\n");
00576 }
00577 } else if (x2 >= 0 && x2 <= gXsize-1) {
00578 gStartX = x2;
00579 gStartY = gYsize-1;
00580 if (y2 >= 0 && y2 <= gYsize-1) {
00581 gEndX = gXsize-1;
00582 gEndY = y2;
00583 } else {
00584 printf("???\n");
00585 }
00586 }
00587
00588 glColor3f(1.0,1.0,1.0);
00589 if (gEndY != -1) {
00590 draw_warp_line(gStartX, gEndX, gStartY, gEndY);
00591 }
00592 }
00593
00594 static void draw_warp_line(double sx, double ex, double sy, double ey)
00595 {
00596 double a, b, c;
00597 double x, y;
00598 double x1, y1;
00599 int i;
00600
00601 a = ey - sy;
00602 b = sx - ex;
00603 c = sy*ex - sx*ey;
00604
00605 glLineWidth(1.0f);
00606 glBegin(GL_LINE_STRIP);
00607 if (a*a >= b*b) {
00608 for (i = -20; i <= gYsize+20; i+=10) {
00609 x = -(b*i + c)/a;
00610 y = i;
00611
00612 arParamIdeal2Observ(dist_factor, x, y, &x1, &y1);
00613 glVertex2f(x1, gYsize-1-y1);
00614 }
00615 } else {
00616 for (i = -20; i <= gXsize+20; i+=10) {
00617 x = i;
00618 y = -(a*i + c)/b;
00619
00620 arParamIdeal2Observ(dist_factor, x, y, &x1, &y1);
00621 glVertex2f(x1, gYsize-1-y1);
00622 }
00623 }
00624 glEnd();
00625 }
00626
00627
00628
00629 static void getCpara(void)
00630 {
00631 double *world_coord;
00632 double *screen_coord;
00633 int point_num;
00634 int i, j, k;
00635
00636 point_num = 0;
00637 for (k = 0; k < loop_num; k++) {
00638 for (i = 0; i < line_num; i++) {
00639 for (j = 0; j < line_num; j++) {
00640 if (inter_coord[k][i][j][0] != -10000.0) point_num++;
00641 }
00642 }
00643 }
00644 arMalloc(world_coord, double, point_num * 3);
00645 arMalloc(screen_coord, double, point_num * 2);
00646
00647 point_num = 0;
00648 for (k = 0; k < loop_num; k++) {
00649 for (i = 0; i < line_num; i++) {
00650 if (line_info[k][i][0] == -1.0) continue;
00651 for (j = 0; j < line_num; j++) {
00652 if (line_info[k][j][0] == -1.0) continue;
00653 if (inter_coord[k][i][j][0] == -10000.0) continue;
00654
00655 world_coord[point_num*3+0] = inter_coord[k][i][j][0];
00656 world_coord[point_num*3+1] = inter_coord[k][i][j][1];
00657 world_coord[point_num*3+2] = inter_coord[k][i][j][2];
00658 intersection(line_info[k][i], line_info[k][j],
00659 &(screen_coord[point_num*2]));
00660
00661 point_num++;
00662 }
00663 }
00664 }
00665 printf("point_num = %d\n", point_num);
00666 if (arParamGet((double (*)[3])world_coord, (double (*)[2])screen_coord, point_num, param.mat) < 0) {
00667 printf("ddd error!!\n");
00668 exit(0);
00669 }
00670
00671 free(world_coord);
00672 free(screen_coord);
00673 }
00674
00675 static void intersection(double line1[4], double line2[4], double *screen_coord)
00676 {
00677 double a, b, c, d, e, f, g;
00678
00679 a = line1[1] - line1[3];
00680 b = line1[2] - line1[0];
00681 c = line1[0] * a + line1[1] * b;
00682 d = line2[1] - line2[3];
00683 e = line2[2] - line2[0];
00684 f = line2[0] * d + line2[1] * e;
00685
00686 g = a*e - b*d;
00687 if (g == 0.0) { printf("???\n"); exit(0); }
00688
00689 screen_coord[0] = (c * e - b * f) / g;
00690 screen_coord[1] = (a * f - c * d) / g;
00691 }