hv_dc1394.cpp
上传用户:lijia5631
上传日期:2008-11-10
资源大小:1214k
文件大小:20k
源码类别:

视频捕捉/采集

开发平台:

MultiPlatform

  1. /**
  2.   * HandVu - a library for computer vision-based hand gesture
  3.   * recognition.
  4.   * Copyright (C) 2004 Mathias Kolsch, matz@cs.ucsb.edu
  5.   *
  6.   * This program is free software; you can redistribute it and/or
  7.   * modify it under the terms of the GNU General Public License
  8.   * as published by the Free Software Foundation; either version 2
  9.   * of the License, or (at your option) any later version.
  10.   *
  11.   * This program is distributed in the hope that it will be useful,
  12.   * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.   * GNU General Public License for more details.
  15.   *
  16.   * You should have received a copy of the GNU General Public License
  17.   * along with this program; if not, write to the Free Software
  18.   * Foundation, Inc., 59 Temple Place - Suite 330, 
  19.   * Boston, MA  02111-1307, USA.
  20.   *
  21.   * $Id: hv_dc1394.cpp,v 1.7 2005/12/08 23:25:41 matz Exp $
  22. **/
  23. // hv_dc1394.c: frame capture from Linux' libdc1394 interface.  This
  24. // code started from Rev 1.4 of dc1394_multiview.c
  25. //
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28. #include <string>
  29. #include <sys/time.h>
  30. #include <sys/mman.h>
  31. #include <sys/ioctl.h>
  32. #include <sys/types.h>
  33. #include <unistd.h>
  34. #include <signal.h>
  35. #include <X11/Xlib.h>
  36. #include <X11/Xutil.h>
  37. #include <X11/extensions/Xvlib.h>
  38. #include <X11/keysym.h>
  39. #include <getopt.h>
  40. #include <libraw1394/raw1394.h>
  41. #include <libdc1394/dc1394_control.h>
  42. // OpenCV
  43. #include <cxcore.h>
  44. #include <cv.h>
  45. // HandVu
  46. #include "Common.h"
  47. #include "HandVu.h"
  48. /* uncomment the following to drop frames to prevent delays */
  49. #define DROP_FRAMES 1
  50. #define MAX_PORTS 3
  51. #define MAX_CAMERAS 8
  52. #define NUM_BUFFERS 8
  53. /* ok the following constant should be by right included thru in Xvlib.h */
  54. #ifndef XV_YV12
  55. #define XV_YV12 0x32315659
  56. #endif
  57. #ifndef XV_YUY2
  58. #define XV_YUY2 0x32595559
  59. #endif
  60. #ifndef XV_UYVY
  61. #define XV_UYVY 0x59565955
  62. #endif
  63. /* declarations for libdc1394 */
  64. int                       numPorts = MAX_PORTS;
  65. raw1394handle_t           handles[MAX_PORTS];
  66. int                       numCameras = 0;
  67. dc1394_cameracapture      cameras[MAX_CAMERAS];
  68. nodeid_t                 *camera_nodes;
  69. dc1394_feature_set        features;
  70. /* declarations for video1394 */
  71. char                     *device_name = NULL;
  72. /* declarations for Xwindows */
  73. Display                  *display = NULL;
  74. Window                    window = (Window) NULL;
  75. long                      width, height;
  76. long                      device_width, device_height;
  77. int                       connection = -1;
  78. XvImage                  *xv_image = NULL;
  79. XvAdaptorInfo            *info;
  80. long                      format = 0;
  81. GC                        gc;
  82. /* declarations for OpenCV and HandVu */
  83. IplImage                 *iplImages[MAX_CAMERAS];
  84. IplImage                 *readOnlyImg = NULL;
  85. char* conductor_fname = "../config/default.conductor";
  86. bool async_processing = false;
  87. int num_async_bufs = 30;
  88. int m_async_bufID = -1;
  89. IplImage *m_async_image = 0;
  90. bool sync_display = async_processing && true;
  91. IplImage* async_display_image = 0;
  92. /* Other declarations */
  93. long                      frame_length;
  94. long                      frame_free;
  95. int                       frame = 0;
  96. int                       adaptor = -1;
  97. int                       freeze = 0;
  98. int                       average = 0;
  99. int                       fps;
  100. int                       res;
  101. int                       fullscreen;
  102. unsigned char            *frame_buffer = NULL;
  103. int                       verbose = 0;
  104. static struct option      long_options[] = {
  105.   {"device", 1, NULL, 0},
  106.   {"fps", 1, NULL, 0},
  107.   {"res", 1, NULL, 0},
  108.   {"fullscreen", 1, NULL, 0},
  109.   {"conductor", 1, NULL, 0},
  110.   {"help", 0, NULL, 0},
  111.   {NULL, 0, 0, 0}
  112. };
  113. void
  114. get_options(int argc, char *argv[])
  115. {
  116.   int option_index = 0;
  117.   fps = 15;
  118.   res = 2;
  119.   fullscreen = 0;
  120.   while (getopt_long(argc, argv, "", long_options, &option_index) >= 0) {
  121.     if (optarg) {
  122.       switch (option_index) {
  123.         /* case values must match long_options */
  124.       case 0:
  125.         device_name = strdup(optarg);
  126.         break;
  127.       case 1:
  128.         fps = atoi(optarg);
  129.         break;
  130.       case 2:
  131.         res = atoi(optarg);
  132.         break;
  133.       case 3:
  134.         fullscreen = atoi(optarg);
  135.         break;
  136.       case 4:
  137.         conductor_fname = strdup(optarg);
  138.         break;
  139.       }
  140.     }
  141.     if (option_index == 5) {
  142.       printf("n"
  143.              "        %s - multi-cam monitor for libdc1394 and XVideonn"
  144.              "Usage:n"
  145.              "        %s [--fps=[1,3,7,15,30]] [--res=[0,1,2]] [--device=/dev/video1394/x]n"
  146.              "             --fps    - frames per second. default=15,n"
  147.              "                        30 not compatible with --res=2n"
  148.              "             --res    - resolution. 0 = 320x240,n"
  149.              "                        1 = 640x480 YUV4:1:1, 2 = 640x480 RGB8 (default)n"
  150.              "             --device - specifies video1394 device to use (optional)n"
  151.              "                        default = /dev/video1394/<port#>n"
  152.              "             --fullscreenn"
  153.              "             --conductor   - handvu configuration filen"
  154.              "             --help   - prints this messagenn"
  155.              "Keyboard Commands:n"
  156.              "        r = reset detectionn"
  157.              "        u = toggle undistortion on/offn"
  158.              "        0-3 = set overlay leveln"
  159.              "        ESC/q = quitn"
  160.              "        < -or- , = decrease scalen"
  161.              "        > -or- . = increase scalen", argv[0], argv[0]);
  162.       exit(0);
  163.     }
  164.   }
  165. }
  166. /* image format conversion functions */
  167. static inline void
  168. iyu12yuy2(unsigned char *src, unsigned char *dest, int NumPixels)
  169. {
  170.   int                       i = 0, j = 0;
  171.   register int              y0, y1, y2, y3, u, v;
  172.   while (i < NumPixels * 3 / 2) {
  173.     u = src[i++];
  174.     y0 = src[i++];
  175.     y1 = src[i++];
  176.     v = src[i++];
  177.     y2 = src[i++];
  178.     y3 = src[i++];
  179.     dest[j++] = y0;
  180.     dest[j++] = u;
  181.     dest[j++] = y1;
  182.     dest[j++] = v;
  183.     dest[j++] = y2;
  184.     dest[j++] = u;
  185.     dest[j++] = y3;
  186.     dest[j++] = v;
  187.   }
  188. }
  189. /* macro by Bart Nabbe */
  190. #define RGB2YUV(r, g, b, y, u, v)
  191.   y = (9798*r + 19235*g + 3736*b)  / 32768;
  192.   u = (-4784*r - 9437*g + 14221*b)  / 32768 + 128;
  193.   v = (20218*r - 16941*g - 3277*b) / 32768 + 128;
  194.   y = y < 0 ? 0 : y;
  195.   u = u < 0 ? 0 : u;
  196.   v = v < 0 ? 0 : v;
  197.   y = y > 255 ? 255 : y;
  198.   u = u > 255 ? 255 : u;
  199.   v = v > 255 ? 255 : v
  200. static inline void
  201. rgb2yuy2(unsigned char *RGB, unsigned char *YUV, int NumPixels)
  202. {
  203.   int                       i, j;
  204.   register int              y0, y1, u0, u1, v0, v1;
  205.   register int              r, g, b;
  206.   for (i = 0, j = 0; i < 3 * NumPixels; i += 6, j += 4) {
  207.     r = RGB[i + 0];
  208.     g = RGB[i + 1];
  209.     b = RGB[i + 2];
  210.     RGB2YUV(r, g, b, y0, u0, v0);
  211.     r = RGB[i + 3];
  212.     g = RGB[i + 4];
  213.     b = RGB[i + 5];
  214.     RGB2YUV(r, g, b, y1, u1, v1);
  215.     YUV[j + 0] = y0;
  216.     YUV[j + 1] = (u0 + u1) / 2;
  217.     YUV[j + 2] = y1;
  218.     YUV[j + 3] = (v0 + v1) / 2;
  219.   }
  220. }
  221. /* helper functions */
  222. void
  223. set_frame_length(long size, int numCameras)
  224. {
  225.   frame_length = size;
  226.   if (verbose) 
  227.     fprintf(stderr, "Setting frame size to %ld kbn", size / 1024);
  228.   frame_free = 0;
  229.   frame_buffer = (unsigned char *) malloc(size * numCameras);
  230. }
  231. void
  232. capture_frame()
  233. {
  234.   static int                have_warned = 0;
  235.   dc1394_dma_multi_capture(cameras, numCameras);
  236.   if (!freeze && adaptor >= 0) {
  237.     for (int i = 0; i < numCameras; i++) {
  238.       // create OpenCV image
  239.       switch (res) {
  240.       case MODE_640x480_YUV411:
  241. if (!have_warned) {
  242.   have_warned = 1;
  243.   printf("WARNING: no OpenCV conversion available for this formatn");
  244. }
  245.         //iyu12yuy2((unsigned char *) cameras[i].capture_buffer,
  246. //        frame_buffer + (i * frame_length),
  247. //        (device_width * device_height));
  248.         break;
  249.       case MODE_320x240_YUV422:
  250.       case MODE_640x480_YUV422:
  251. if (!have_warned) {
  252.   have_warned = 1;
  253.   printf("WARNING: no OpenCV conversion available for this formatn");
  254. }
  255. //        memcpy(frame_buffer + (i * frame_length),
  256. //     cameras[i].capture_buffer, device_width * device_height * 2);
  257.         break;
  258.       case MODE_640x480_RGB:
  259. // don't convert for OpenCV, this is the correct format
  260. readOnlyImg->imageData = (char *) cameras[i].capture_buffer;
  261.         if (async_processing) {
  262.           if (i==0) {
  263.             hvAsyncGetImageBuffer(&m_async_image, &m_async_bufID);
  264.             cvCopy(readOnlyImg, m_async_image);
  265.           }
  266.         } else {
  267.           cvCopy(readOnlyImg, iplImages[i]);
  268.         }
  269.         break;
  270.       }
  271.       
  272.       if (verbose) {
  273.         CvFont                    font;
  274.         cvInitFont(&font, CV_FONT_VECTOR0, 0.5f /* hscale */ ,
  275.                    0.5f /* vscale */ , 0.1f /*italic_scale */ ,
  276.                    1 /* thickness */ , 8);
  277.         char                      str[256];
  278.         sprintf(str, "camera id: %d", i);
  279.         CvSize                    textsize;
  280.         int                       underline;
  281.         cvGetTextSize(str, &font, &textsize, &underline);
  282.         CvPoint                   pos =
  283.           cvPoint(iplImages[i]->width - textsize.width - 5,
  284.                   textsize.height + 10);
  285.         cvPutText(iplImages[i], str, pos, &font, CV_RGB(0, 255, 0));
  286. //        cvRectangle(iplImages[i], cvPoint(10, 10), cvPoint(100, 100),
  287.         //            cvScalar(255, 255, 255, 255), CV_FILLED, 8, 0);
  288.       }
  289.     }
  290.   }
  291.   for (int i = 0; i < numCameras; i++) {
  292.     dc1394_dma_done_with_buffer(&cameras[i]);
  293.   }
  294. }
  295. void process_frame()
  296. {
  297.   if (!freeze && adaptor >= 0) {
  298.     // main HandVu call
  299.     if (async_processing) {
  300.       hvAsyncProcessFrame(m_async_bufID);
  301.     } else {
  302.       hvProcessFrame(iplImages[0], iplImages[1]);
  303.     }
  304.   }
  305. }
  306. void display_frame()
  307. {
  308.   if (!freeze && adaptor >= 0) {
  309.     // copy into frame buffer for display
  310.     for (int i = 0; i < numCameras; i++) {
  311.       if (sync_display && i==0) {
  312.         rgb2yuy2((unsigned char *) async_display_image->imageData,
  313.                  frame_buffer + (i * frame_length),
  314.                  (device_width * device_height));
  315.       } else {
  316.         rgb2yuy2((unsigned char *) iplImages[i]->imageData,
  317.                  frame_buffer + (i * frame_length),
  318.                  (device_width * device_height));
  319.       }
  320.    }
  321.     xv_image =
  322.       XvCreateImage(display, info[adaptor].base_id, format, 
  323.     (char*) frame_buffer,
  324.                     device_width, device_height * numCameras);
  325.     XvPutImage(display, info[adaptor].base_id, window, gc, xv_image, 0, 0,
  326.                device_width, device_height * numCameras, 0, 0, width, height);
  327.     xv_image = NULL;
  328.   }
  329.   XFlush(display);
  330. }
  331. void displayCallback(IplImage* image, hvAction action)
  332. {
  333.   if (sync_display) {
  334.     cvCopy(image, async_display_image);
  335.   } else {
  336.     cvCopy(image, iplImages[0]);
  337.     display_frame();
  338.   }
  339. }
  340. void
  341. cleanup(void)
  342. {
  343.   int                       i;
  344.   for (i = 0; i < numCameras; i++) {
  345.     dc1394_dma_unlisten(handles[cameras[i].port], &cameras[i]);
  346.     dc1394_dma_release_camera(handles[cameras[i].port], &cameras[i]);
  347.   }
  348.   for (i = 0; i < numPorts; i++)
  349.     raw1394_destroy_handle(handles[i]);
  350.   if ((void *) window != NULL)
  351.     XUnmapWindow(display, window);
  352.   if (display != NULL)
  353.     XFlush(display);
  354.   if (frame_buffer != NULL)
  355.     free(frame_buffer);
  356.   // OpenCV cleanup
  357.   for (i = 0; i < numCameras; i++) {
  358.     cvReleaseImageHeader(&iplImages[i]);
  359.   }
  360. }
  361. void
  362. handle_events()
  363. {
  364.   XEvent                    xev;
  365.   while (XPending(display) > 0) {
  366.     XNextEvent(display, &xev);
  367.     switch (xev.type) {
  368.     case ConfigureNotify:
  369.       width = xev.xconfigure.width;
  370.       height = xev.xconfigure.height;
  371.       //      capture_frame();
  372.       //      process_frame();
  373.       display_frame();
  374.       break;
  375.     case KeyPress:
  376.       switch (XKeycodeToKeysym(display, xev.xkey.keycode, 0)) {
  377.       case XK_q:
  378.       case XK_Q:
  379.       case XK_Escape:
  380.         cleanup();
  381.         exit(0);
  382.         break;
  383.       case XK_r:
  384.       case XK_R:
  385. hvStopRecognition();
  386. hvStartRecognition();
  387.         break;
  388.       case XK_u:
  389.       case XK_U:
  390.         if (hvCanCorrectDistortion()) {
  391.           hvCorrectDistortion(!hvIsCorrectingDistortion());
  392.         }
  393.         break;
  394.       case XK_comma:
  395.       case XK_less:
  396.         width = (width*3)/4;
  397.         height = (height*3)/4;
  398.         XResizeWindow(display, window, width, height);
  399.         //        capture_frame();
  400.         //        process_frame();
  401.         display_frame();
  402.         break;
  403.       case XK_period:
  404.       case XK_greater:
  405.         width = (int) (1.25 * width);
  406.         height = (int) (1.25 * height);
  407.         XResizeWindow(display, window, width, height);
  408.         //        capture_frame();
  409.         //        process_frame();
  410.         display_frame();
  411.         break;
  412.       case XK_0:
  413. hvSetOverlayLevel(0);
  414.         break;
  415.       case XK_1:
  416. hvSetOverlayLevel(1);
  417.         break;
  418.       case XK_2:
  419. hvSetOverlayLevel(2);
  420.         break;
  421.       case XK_3:
  422. hvSetOverlayLevel(3);
  423.         break;
  424.       }
  425.       break;
  426.     }
  427.   }
  428. }
  429. void
  430. QueryXv()
  431. {
  432.   int                       num_adaptors;
  433.   int                       num_formats;
  434.   XvImageFormatValues      *formats = NULL;
  435.   int                       i, j;
  436.   char                      xv_name[5];
  437.   XvQueryAdaptors(display, DefaultRootWindow(display),
  438.   (unsigned int*) &num_adaptors, &info);
  439.   for (i = 0; i < num_adaptors; i++) {
  440.     formats = XvListImageFormats(display, info[i].base_id, &num_formats);
  441.     for (j = 0; j < num_formats; j++) {
  442.       xv_name[4] = 0;
  443.       memcpy(xv_name, &formats[j].id, 4);
  444.       if (formats[j].id == format) {
  445.         if (verbose) 
  446.   fprintf(stderr, "using Xv format 0x%x %s %sn", formats[j].id,
  447.   xv_name,
  448.   (formats[j].format == XvPacked) ? "packed" : "planar");
  449.         if (adaptor < 0)
  450.           adaptor = i;
  451.       }
  452.     }
  453.   }
  454.   XFree(formats);
  455.   if (adaptor < 0)
  456.     fprintf(stderr, "No suitable Xv adaptor found");
  457. }
  458. /* trap ctrl-c */
  459. void
  460. signal_handler(int sig)
  461. {
  462.   signal(SIGINT, SIG_IGN);
  463.   cleanup();
  464.   exit(0);
  465. }
  466. void
  467. set_manual_exposure_gain(int camID, int exposure, int gain)
  468. {
  469.   int                       success =
  470.     dc1394_auto_on_off(handles[cameras[camID].port], cameras[camID].node,
  471.                        FEATURE_EXPOSURE, DC1394_FALSE);
  472.   if (success != DC1394_SUCCESS) {
  473.     fprintf(stderr, "can not turn off camera auto exposuren");
  474.     return;
  475.   }
  476.   success =
  477.     dc1394_set_exposure(handles[cameras[camID].port], cameras[camID].node,
  478.                         exposure);
  479.   if (success != DC1394_SUCCESS) {
  480.     fprintf(stderr, "set_exposure returned %dn", success);
  481.     return;
  482.   }
  483.   success =
  484.     dc1394_set_gain(handles[cameras[camID].port], cameras[camID].node, gain);
  485.   if (success != DC1394_SUCCESS) {
  486.     fprintf(stderr, "set_gain returned %dn", success);
  487.     return;
  488.   }
  489. }
  490. int
  491. main(int argc, char *argv[])
  492. {
  493.   XGCValues                 xgcv;
  494.   long                      background = 0x010203;
  495.   unsigned int              channel;
  496.   unsigned int              speed;
  497.   int                       i, p, cn;
  498.   raw1394handle_t           raw_handle;
  499.   struct raw1394_portinfo   ports[MAX_PORTS];
  500.   get_options(argc, argv);
  501.   /* process options */
  502.   switch (fps) {
  503.   case 1:
  504.     fps = FRAMERATE_1_875;
  505.     break;
  506.   case 3:
  507.     fps = FRAMERATE_3_75;
  508.     break;
  509.   case 15:
  510.     fps = FRAMERATE_15;
  511.     break;
  512.   case 30:
  513.     fps = FRAMERATE_30;
  514.     break;
  515.   case 60:
  516.     fps = FRAMERATE_60;
  517.     break;
  518.   default:
  519.     fps = FRAMERATE_7_5;
  520.     break;
  521.   }
  522.   switch (res) {
  523.   case 1:
  524.     res = MODE_640x480_YUV411;
  525.     device_width = 640;
  526.     device_height = 480;
  527.     format = XV_YUY2;
  528.     break;
  529.   case 2:
  530.     res = MODE_640x480_RGB;
  531.     device_width = 640;
  532.     device_height = 480;
  533.     format = XV_YUY2;
  534.     break;
  535.   default:
  536.     res = MODE_320x240_YUV422;
  537.     device_width = 320;
  538.     device_height = 240;
  539.     format = XV_UYVY;
  540.     break;
  541.   }
  542.   /* get the number of ports (cards) */
  543.   raw_handle = raw1394_new_handle();
  544.   if (raw_handle == NULL) {
  545.     perror("Unable to aquire a raw1394 handlen");
  546.     perror("did you load the drivers?n");
  547.     exit(-1);
  548.   }
  549.   numPorts = raw1394_get_port_info(raw_handle, ports, numPorts);
  550.   raw1394_destroy_handle(raw_handle);
  551.   if (verbose) printf("number of ports = %dn", numPorts);
  552.   /* get dc1394 handle to each port */
  553.   for (p = 0; p < numPorts; p++) {
  554.     int                       camCount;
  555.     handles[p] = dc1394_create_handle(p);
  556.     if (handles[p] == NULL) {
  557.       perror("Unable to aquire a raw1394 handlen");
  558.       perror("did you load the drivers?n");
  559.       cleanup();
  560.       exit(-1);
  561.     }
  562.     /* get the camera nodes and describe them as we find them */
  563.     camera_nodes = dc1394_get_camera_nodes(handles[p], &camCount, verbose);
  564.     /* setup cameras for capture */
  565.     for (i = 0; i < camCount; i++) {
  566.       cameras[numCameras].node = camera_nodes[i];
  567.       if (dc1394_get_camera_feature_set
  568.           (handles[p], cameras[numCameras].node,
  569.            &features) != DC1394_SUCCESS) {
  570.         printf("unable to get feature setn");
  571.       } else if (verbose) {
  572.         dc1394_print_feature_set(&features);
  573.       }
  574.       if (dc1394_get_iso_channel_and_speed
  575.           (handles[p], cameras[numCameras].node, &channel,
  576.            &speed) != DC1394_SUCCESS) {
  577.         printf("unable to get the iso channel numbern");
  578.         cleanup();
  579.         exit(-1);
  580.       }
  581.       if (dc1394_dma_setup_capture
  582.           (handles[p], cameras[numCameras].node, i + 1 /*channel */ ,
  583.            FORMAT_VGA_NONCOMPRESSED, res, SPEED_400, fps, NUM_BUFFERS,
  584.            DROP_FRAMES, device_name,
  585.            &cameras[numCameras]) != DC1394_SUCCESS) {
  586.         fprintf(stderr,
  587.                 "unable to setup camera - check line %d of %s to make suren",
  588.                 __LINE__, __FILE__);
  589.         perror("that the video mode, framerate and format are supportedn");
  590.         printf("by your camera(s)n");
  591.         cleanup();
  592.         exit(-1);
  593.       }
  594.       /*have the camera start sending us data */
  595.       if (dc1394_start_iso_transmission
  596.           (handles[p], cameras[numCameras].node) != DC1394_SUCCESS) {
  597.         perror("unable to start camera iso transmissionn");
  598.         cleanup();
  599.         exit(-1);
  600.       }
  601.       numCameras++;
  602.     }
  603.   }
  604.   fflush(stdout);
  605.   if (numCameras < 1) {
  606.     perror("no cameras found :(n");
  607.     cleanup();
  608.     exit(-1);
  609.   }
  610.   //set_manual_exposure_gain(0, 440, 30);
  611.   switch (format) {
  612.   case XV_YV12:
  613.     set_frame_length(device_width * device_height * 3 / 2, numCameras);
  614.     break;
  615.   case XV_YUY2:
  616.   case XV_UYVY:
  617.     set_frame_length(device_width * device_height * 2, numCameras);
  618.     break;
  619.   default:
  620.     fprintf(stderr, "Unknown format set (internal error)n");
  621.     exit(255);
  622.   }
  623.   /* create OpenCV image wrappers */
  624.   for (cn = 0; cn < MAX_CAMERAS; cn++) {
  625.     if (cn < numCameras) {
  626.       iplImages[cn] =
  627.         cvCreateImage(cvSize(device_width, device_height),
  628.       IPL_DEPTH_8U, 3);
  629.       readOnlyImg =
  630.         cvCreateImageHeader(cvSize(device_width, device_height),
  631.                             IPL_DEPTH_8U, 3);
  632.     } else {
  633.       iplImages[cn] = NULL;
  634.     }
  635.   }
  636.   /* initialize handvu */
  637.   hvInitialize(device_width, device_height);
  638.   hvLoadConductor(string(conductor_fname));
  639.   hvStartRecognition();
  640.   hvSetOverlayLevel(3);
  641.   if (async_processing) {
  642.     hvAsyncSetup(num_async_bufs, displayCallback);
  643.     hvAsyncGetImageBuffer(&m_async_image, &m_async_bufID);
  644.     if (sync_display) async_display_image = cvCloneImage(iplImages[0]);
  645.   }  
  646.   /* make the window */
  647.   display = XOpenDisplay(getenv("DISPLAY"));
  648.   if (display == NULL) {
  649.     fprintf(stderr, "Could not open display "%s"n", getenv("DISPLAY"));
  650.     cleanup();
  651.     exit(-1);
  652.   }
  653.   QueryXv();
  654.   if (adaptor < 0) {
  655.     cleanup();
  656.     exit(-1);
  657.   }
  658.   width = device_width;
  659.   height = device_height * numCameras;
  660.   window =
  661.     XCreateSimpleWindow(display, DefaultRootWindow(display), 0, 0,
  662.                         width, height, 0, WhitePixel(display,
  663.                                                      DefaultScreen
  664.                                                      (display)), background);
  665.   XSelectInput(display, window, StructureNotifyMask | KeyPressMask);
  666.   XMapWindow(display, window);
  667.   connection = ConnectionNumber(display);
  668.   gc = XCreateGC(display, window, 0, &xgcv);
  669.   /* local main event loop */
  670.   while (1) {
  671.     if (async_processing) {
  672.       // asynchronous processing in HandVu
  673.       capture_frame();
  674.       process_frame();
  675.       if (sync_display) display_frame();
  676.       handle_events();
  677.       
  678.     } else {
  679.       // synchronous processing in HandVu
  680.       capture_frame();
  681.       process_frame();
  682.       display_frame();
  683.       handle_events();
  684.     }
  685.     /* XPending */
  686.   }                             /* while not interrupted */
  687.   exit(0);
  688. }