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
00026
00027
00028 #include <stdio.h>
00029 #include <string.h>
00030 #include <unistd.h>
00031 #include <cstdlib>
00032 #include "libfreenect.h"
00033
00034 #include <pthread.h>
00035
00036 #if defined(__APPLE__)
00037 #include <GLUT/glut.h>
00038 #include <OpenGL/gl.h>
00039 #include <OpenGL/glu.h>
00040 #else
00041 #include <GL/glut.h>
00042 #include <GL/gl.h>
00043 #include <GL/glu.h>
00044 #endif
00045
00046 #include <math.h>
00047
00048 #include <opencv2/core/core.hpp>
00049 #include <opencv2/calib3d/calib3d.hpp>
00050 #include <opencv2/highgui/highgui.hpp>
00051 #include <opencv2/imgproc/imgproc.hpp>
00052
00053 using namespace std;
00054
00055
00056 #define ROWS 480
00057 #define COLS 640
00058
00059
00060 cv::Size pattern_size;
00061
00062
00063 char *fdir = NULL;
00064 int ir_num = 0;
00065 int rgb_num = 0;
00066 int depth_num = 0;
00067 int s_num = 0;
00068 bool saveIR = false;
00069 bool saveRGB = false;
00070 bool saveDepth = false;
00071
00072 pthread_t freenect_thread;
00073 volatile int die = 0;
00074
00075 int window;
00076 int ir_mode = 0;
00077
00078 pthread_mutex_t gl_backbuf_mutex = PTHREAD_MUTEX_INITIALIZER;
00079
00080 uint8_t gl_depth_front[640 * 480 * 4];
00081 uint8_t gl_depth_back[640 * 480 * 4];
00082
00083 uint8_t gl_rgb_front[640 * 480 * 4];
00084 uint8_t gl_rgb_back[640 * 480 * 4];
00085
00086 GLuint gl_depth_tex;
00087 GLuint gl_rgb_tex;
00088
00089 freenect_context *f_ctx;
00090 freenect_device *f_dev;
00091 int freenect_angle = 0;
00092 int freenect_angle_last = 0;
00093 int freenect_led;
00094
00095
00096 pthread_cond_t gl_frame_cond = PTHREAD_COND_INITIALIZER;
00097 int got_frames = 0;
00098
00099 void
00100 DrawGLScene ()
00101 {
00102 pthread_mutex_lock (&gl_backbuf_mutex);
00103
00104 while (got_frames < 2)
00105 {
00106 pthread_cond_wait (&gl_frame_cond, &gl_backbuf_mutex);
00107 }
00108
00109 memcpy (gl_depth_front, gl_depth_back, sizeof (gl_depth_back));
00110 memcpy (gl_rgb_front, gl_rgb_back, sizeof (gl_rgb_back));
00111 got_frames = 0;
00112 pthread_mutex_unlock (&gl_backbuf_mutex);
00113
00114 glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00115 glLoadIdentity ();
00116
00117 glEnable (GL_TEXTURE_2D);
00118
00119 glBindTexture (GL_TEXTURE_2D, gl_depth_tex);
00120 glTexImage2D (GL_TEXTURE_2D, 0, 3, 640, 480, 0, GL_RGB, GL_UNSIGNED_BYTE, gl_depth_front);
00121
00122 glBegin (GL_TRIANGLE_FAN);
00123 glColor4f (255.0f, 255.0f, 255.0f, 255.0f);
00124 glTexCoord2f (0, 0);
00125 glVertex3f (0, 0, 0);
00126 glTexCoord2f (1, 0);
00127 glVertex3f (640, 0, 0);
00128 glTexCoord2f (1, 1);
00129 glVertex3f (640, 480, 0);
00130 glTexCoord2f (0, 1);
00131 glVertex3f (0, 480, 0);
00132 glEnd ();
00133
00134 glBindTexture (GL_TEXTURE_2D, gl_rgb_tex);
00135 glTexImage2D (GL_TEXTURE_2D, 0, 3, 640, 480, 0, GL_RGB, GL_UNSIGNED_BYTE, gl_rgb_front);
00136
00137 glBegin (GL_TRIANGLE_FAN);
00138 glColor4f (255.0f, 255.0f, 255.0f, 255.0f);
00139 glTexCoord2f (0, 0);
00140 glVertex3f (640, 0, 0);
00141 glTexCoord2f (1, 0);
00142 glVertex3f (1280, 0, 0);
00143 glTexCoord2f (1, 1);
00144 glVertex3f (1280, 480, 0);
00145 glTexCoord2f (0, 1);
00146 glVertex3f (640, 480, 0);
00147 glEnd ();
00148
00149 glutSwapBuffers ();
00150 }
00151
00152
00153
00154 void
00155 keyPressed (unsigned char key, int x, int y)
00156 {
00157 if (key == 27)
00158 {
00159 die = 1;
00160 pthread_join (freenect_thread, NULL);
00161 glutDestroyWindow (window);
00162 pthread_exit (NULL);
00163 }
00164 if (key == 'w')
00165 {
00166 freenect_angle++;
00167 if (freenect_angle > 30)
00168 {
00169 freenect_angle = 30;
00170 }
00171 }
00172 if (key == 'c')
00173 {
00174 freenect_angle = 0;
00175 }
00176 if (key == 'x')
00177 {
00178 freenect_angle--;
00179 if (freenect_angle < -30)
00180 {
00181 freenect_angle = -30;
00182 }
00183 }
00184
00185 if (key == 'i')
00186 {
00187 if (ir_mode)
00188 {
00189 freenect_set_rgb_format (f_dev, FREENECT_FORMAT_RGB);
00190 freenect_start_rgb (f_dev);
00191 }
00192 else
00193 {
00194 freenect_set_rgb_format (f_dev, FREENECT_FORMAT_IR);
00195 freenect_start_ir (f_dev);
00196 }
00197 ir_mode = !ir_mode;
00198 }
00199
00200
00201 if (key == 's')
00202 {
00203 if (ir_mode) saveIR = true;
00204 else
00205 {
00206 saveRGB = true;
00207 saveDepth = true;
00208 }
00209 }
00210
00211
00212 if (key == 'b')
00213 {
00214 if (ir_mode) ir_num--;
00215 else { rgb_num--; depth_num--; }
00216 }
00217
00218 if (key == '1')
00219 {
00220 freenect_set_led (f_dev, LED_GREEN);
00221 }
00222 if (key == '2')
00223 {
00224 freenect_set_led (f_dev, LED_RED);
00225 }
00226 if (key == '3')
00227 {
00228 freenect_set_led (f_dev, LED_YELLOW);
00229 }
00230 if (key == '4')
00231 {
00232 freenect_set_led (f_dev, LED_BLINK_YELLOW);
00233 }
00234 if (key == '5')
00235 {
00236 freenect_set_led (f_dev, LED_BLINK_GREEN);
00237 }
00238 if (key == '6')
00239 {
00240 freenect_set_led (f_dev, LED_BLINK_RED_YELLOW);
00241 }
00242 if (key == '0')
00243 {
00244 freenect_set_led (f_dev, LED_OFF);
00245 }
00246
00247 if (freenect_angle != freenect_angle_last)
00248 freenect_set_tilt_degs (f_dev, freenect_angle);
00249 freenect_angle_last = freenect_angle;
00250 }
00251
00252 void
00253 ReSizeGLScene (int Width, int Height)
00254 {
00255 glViewport (0, 0, Width, Height);
00256 glMatrixMode (GL_PROJECTION);
00257 glLoadIdentity ();
00258 glOrtho (0, 1280, 480, 0, -1.0f, 1.0f);
00259 glMatrixMode (GL_MODELVIEW);
00260 }
00261
00262 void
00263 InitGL (int Width, int Height)
00264 {
00265 glClearColor (0.0f, 0.0f, 0.0f, 0.0f);
00266 glClearDepth (1.0);
00267 glDepthFunc (GL_LESS);
00268 glDisable (GL_DEPTH_TEST);
00269 glEnable (GL_BLEND);
00270 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00271 glShadeModel (GL_SMOOTH);
00272 glGenTextures (1, &gl_depth_tex);
00273 glBindTexture (GL_TEXTURE_2D, gl_depth_tex);
00274 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00275 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00276 glGenTextures (1, &gl_rgb_tex);
00277 glBindTexture (GL_TEXTURE_2D, gl_rgb_tex);
00278 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00279 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00280 ReSizeGLScene (Width, Height);
00281 }
00282
00283 void *
00284 gl_threadfunc (void *arg)
00285 {
00286 glutInitDisplayMode (GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH);
00287 glutInitWindowSize (1280, 480);
00288 glutInitWindowPosition (0, 0);
00289
00290 window = glutCreateWindow ("Calibration Data Acquisition");
00291
00292 glutDisplayFunc (&DrawGLScene);
00293 glutIdleFunc (&DrawGLScene);
00294 glutReshapeFunc (&ReSizeGLScene);
00295 glutKeyboardFunc (&keyPressed);
00296
00297 InitGL (1280, 480);
00298
00299 glutMainLoop ();
00300
00301 return NULL;
00302 }
00303
00304 uint16_t t_gamma[2048];
00305 uint8_t ir_gamma[1024];
00306 uint8_t g_gamma[256];
00307
00308 void
00309 depth_cb (freenect_device * dev, void *v_depth, uint32_t timestamp)
00310 {
00311 int i;
00312 freenect_depth *depth = (freenect_depth *)v_depth;
00313
00314
00315 if (saveDepth)
00316 {
00317 cv::Mat img(ROWS,COLS,CV_16UC1);
00318 uint8_t *imgi = img.ptr<uint8_t>(0);
00319 uint8_t *rgbi = (uint8_t *)depth;
00320 memcpy(imgi,rgbi,FREENECT_FRAME_PIX*2);
00321 char fname[1024];
00322 sprintf(fname,"%s/img_depth_%02d.png", fdir, depth_num);
00323 depth_num++;
00324 if (cv::imwrite(fname,img))
00325 printf("Wrote depth image %s\n", fname);
00326 else
00327 printf("ERROR: failed to write image %s\n", fname);
00328 saveDepth = false;
00329 }
00330
00331
00332 pthread_mutex_lock (&gl_backbuf_mutex);
00333 for (i = 0; i < FREENECT_FRAME_PIX; i++)
00334 {
00335 int pval = t_gamma[depth[i]];
00336 int lb = pval & 0xff;
00337 switch (pval >> 8)
00338 {
00339 case 0:
00340 gl_depth_back[3 * i + 0] = 255;
00341 gl_depth_back[3 * i + 1] = 255 - lb;
00342 gl_depth_back[3 * i + 2] = 255 - lb;
00343 break;
00344 case 1:
00345 gl_depth_back[3 * i + 0] = 255;
00346 gl_depth_back[3 * i + 1] = lb;
00347 gl_depth_back[3 * i + 2] = 0;
00348 break;
00349 case 2:
00350 gl_depth_back[3 * i + 0] = 255 - lb;
00351 gl_depth_back[3 * i + 1] = 255;
00352 gl_depth_back[3 * i + 2] = 0;
00353 break;
00354 case 3:
00355 gl_depth_back[3 * i + 0] = 0;
00356 gl_depth_back[3 * i + 1] = 255;
00357 gl_depth_back[3 * i + 2] = lb;
00358 break;
00359 case 4:
00360 gl_depth_back[3 * i + 0] = 0;
00361 gl_depth_back[3 * i + 1] = 255 - lb;
00362 gl_depth_back[3 * i + 2] = 255;
00363 break;
00364 case 5:
00365 gl_depth_back[3 * i + 0] = 0;
00366 gl_depth_back[3 * i + 1] = 0;
00367 gl_depth_back[3 * i + 2] = 255 - lb;
00368 break;
00369 default:
00370 gl_depth_back[3 * i + 0] = 0;
00371 gl_depth_back[3 * i + 1] = 0;
00372 gl_depth_back[3 * i + 2] = 0;
00373 break;
00374 }
00375 }
00376 got_frames++;
00377 pthread_cond_signal (&gl_frame_cond);
00378 pthread_mutex_unlock (&gl_backbuf_mutex);
00379 }
00380
00381 void
00382 rgb_cb (freenect_device * dev, freenect_pixel * rgb, uint32_t timestamp)
00383 {
00384 pthread_mutex_lock (&gl_backbuf_mutex);
00385 got_frames++;
00386 memcpy (gl_rgb_back, rgb, FREENECT_RGB_SIZE);
00387
00388
00389 cv::Mat img(ROWS,COLS,CV_8UC3);
00390 uint8_t *imgi = img.ptr<uint8_t>(0);
00391 uint8_t *rgbi = (uint8_t *)rgb;
00392 for (int i=0; i<FREENECT_FRAME_PIX; i++)
00393 {
00394 imgi[i*3+2] = rgbi[i*3];
00395 imgi[i*3+1] = rgbi[i*3+1];
00396 imgi[i*3] = rgbi[i*3+2];
00397 }
00398
00399 vector<cv::Point2f> corners;
00400 bool ret = cv::findChessboardCorners(img, pattern_size, corners);
00401
00402
00403 cv::Mat imgc;
00404 imgc = img.clone();
00405 if (corners.size() > 0)
00406 drawChessboardCorners(imgc, pattern_size, cv::Mat(corners), ret);
00407
00408
00409 imgi = imgc.ptr<uint8_t>(0);
00410 for (int i=0; i<FREENECT_FRAME_PIX; i++)
00411 {
00412 gl_rgb_back[3*i + 0] = imgi[i*3+2];
00413 gl_rgb_back[3*i + 1] = imgi[i*3+1];
00414 gl_rgb_back[3*i + 2] = imgi[i*3];
00415 }
00416
00417 if (saveRGB && ret)
00418 {
00419 char fname[1024];
00420 sprintf(fname,"%s/img_rgb_%02d.png", fdir, rgb_num);
00421 rgb_num++;
00422 if (cv::imwrite(fname,img))
00423 printf("Wrote RGB image %s\n", fname);
00424 else
00425 printf("ERROR: failed to write image %s\n", fname);
00426 saveRGB = false;
00427 }
00428
00429
00430 pthread_cond_signal (&gl_frame_cond);
00431 pthread_mutex_unlock (&gl_backbuf_mutex);
00432 }
00433
00434 void
00435 ir_cb (freenect_device * dev, freenect_pixel_ir * rgb, uint32_t timestamp)
00436 {
00437 pthread_mutex_lock (&gl_backbuf_mutex);
00438 got_frames++;
00439
00440 int i;
00441 for (i = 0; i < FREENECT_FRAME_PIX; i++)
00442 {
00443 int pval = rgb[i];
00444 int lb = ir_gamma[pval];
00445
00446 gl_rgb_back[3 * i + 0] = lb;
00447 gl_rgb_back[3 * i + 1] = lb;
00448 gl_rgb_back[3 * i + 2] = lb;
00449 }
00450
00451
00452 cv::Mat img(ROWS,COLS,CV_8UC1);
00453 uint8_t *imgi = img.ptr<uint8_t>(0);
00454 for (i = 0; i < FREENECT_FRAME_PIX; i++)
00455
00456 imgi[i] = (uint8_t)ir_gamma[rgb[i]];
00457
00458 vector<cv::Point2f> corners;
00459 bool ret = cv::findChessboardCorners(img, pattern_size, corners);
00460
00461
00462 cv::Mat imgc(ROWS,COLS,CV_8UC3);
00463 cv::cvtColor(img,imgc,CV_GRAY2RGB,3);
00464 if (corners.size() > 0)
00465 drawChessboardCorners(imgc, pattern_size, cv::Mat(corners), ret);
00466
00467
00468 imgi = imgc.ptr<uint8_t>(0);
00469 for (i = 0; i < FREENECT_FRAME_PIX; i++)
00470 {
00471 gl_rgb_back[3*i + 0] = imgi[i*3];
00472 gl_rgb_back[3*i + 1] = imgi[i*3+1];
00473 gl_rgb_back[3*i + 2] = imgi[i*3+2];
00474 }
00475
00476 if (saveIR && ret)
00477 {
00478 char fname[1024];
00479 sprintf(fname,"%s/img_ir_%02d.png", fdir, ir_num);
00480 ir_num++;
00481 if (cv::imwrite(fname,img))
00482 printf("Wrote IR image %s\n", fname);
00483 else
00484 printf("ERROR: failed to write image %s\n", fname);
00485 saveIR = false;
00486 }
00487
00488 pthread_cond_signal (&gl_frame_cond);
00489 pthread_mutex_unlock (&gl_backbuf_mutex);
00490 }
00491
00492 void *
00493 freenect_threadfunc (void *arg)
00494 {
00495 freenect_set_tilt_degs (f_dev, freenect_angle);
00496 freenect_set_led (f_dev, LED_RED);
00497 freenect_set_depth_callback (f_dev, depth_cb);
00498 freenect_set_rgb_callback (f_dev, rgb_cb);
00499 freenect_set_ir_callback (f_dev, ir_cb);
00500 freenect_set_rgb_format (f_dev, FREENECT_FORMAT_RGB);
00501 freenect_set_depth_format (f_dev, FREENECT_FORMAT_11_BIT);
00502
00503 freenect_start_depth (f_dev);
00504 freenect_start_rgb (f_dev);
00505
00506 printf ("'w'-tilt up, 'c'-center, 'x'-tilt down, '0'-'6'-select LED mode\n");
00507
00508 while (!die && freenect_process_events (f_ctx) >= 0)
00509 {}
00510
00511 printf ("\nshutting down streams...\n");
00512
00513 freenect_stop_depth (f_dev);
00514 freenect_stop_rgb (f_dev);
00515 freenect_stop_ir (f_dev);
00516
00517 printf ("-- done!\n");
00518 return NULL;
00519 }
00520
00521 int
00522 main(int argc, char **argv)
00523 {
00524
00525 glutInit (&argc, argv);
00526
00527 pattern_size = cv::Size(0,0);
00528 opterr = 0;
00529 int c;
00530 while ((c = getopt(argc, argv, "r:c:")) != -1)
00531 {
00532 switch (c)
00533 {
00534 case 'r':
00535 pattern_size.height = atoi(optarg);
00536 break;
00537 case 'c':
00538 pattern_size.width = atoi(optarg);
00539 break;
00540 }
00541 }
00542
00543 if (optind < argc)
00544 fdir = argv[optind];
00545
00546 if (pattern_size.width == 0 || pattern_size.height == 0 || fdir == NULL)
00547 {
00548 printf("Must give the checkerboard width/height and data directory.\n"
00549 "Usage:\n"
00550 "%s -r ROWS -c COLS my_data_dir\n", argv[0]);
00551 return 1;
00552 }
00553
00554 int i;
00555 for (i = 0; i < 2048; i++)
00556 {
00557 float v = i / 2048.0;
00558 v = powf (v, 3) * 6;
00559 t_gamma[i] = v * 6 * 256;
00560 }
00561
00562 for (i = 0; i < 1024; i++)
00563 {
00564 float v = i / 1024.0;
00565 v = powf (v, 0.45);
00566 ir_gamma[i] = v * 256;
00567 }
00568
00569 for (i = 0; i < 256; i++)
00570 {
00571 float v = i / 256.0;
00572 v = powf (v, 0.45);
00573 g_gamma[i] = v * 256;
00574 }
00575
00576 if (freenect_init (&f_ctx, NULL) < 0)
00577 {
00578 printf ("freenect_init() failed\n");
00579 return 1;
00580 }
00581
00582 freenect_set_log_level (f_ctx, FREENECT_LOG_ERROR);
00583
00584 int nr_devices = freenect_num_devices (f_ctx);
00585 printf ("Number of devices found: %d\n", nr_devices);
00586
00587 int user_device_number = 0;
00588 if (argc > 1)
00589 user_device_number = atoi (argv[1]);
00590
00591 if (nr_devices < 1)
00592 return 1;
00593
00594 if (freenect_open_device (f_ctx, &f_dev, user_device_number) < 0)
00595 {
00596 printf ("Could not open device\n");
00597 return 1;
00598 }
00599
00600 if (pthread_create (&freenect_thread, NULL, freenect_threadfunc, NULL))
00601 {
00602 printf ("pthread_create failed\n");
00603 return 1;
00604 }
00605
00606
00607 gl_threadfunc (NULL);
00608
00609 return 0;
00610 }