libcvautomation  1.2
cva-match.c
Go to the documentation of this file.
00001 /*
00002  * =====================================================================================
00003  *
00004  *       Filename:  cva-match.c
00005  *
00006  *    Description:  Match an image to its parent image, and return the coordinates
00007  *
00008  *        Version:  0.1
00009  *        Created:  06/20/2012
00010  *       Revision:  none
00011  *       Compiler:  gcc
00012  *
00013  *         Author:  Bradlee Speice, bspeice@uncc.edu
00014  *   Organization:  MOSAIC at University of North Carolina at Charlotte
00015  *
00016  * =====================================================================================
00017  */
00018 #include <stdlib.h>
00019 #include <stdio.h>
00020 #include <unistd.h>
00021 #include <getopt.h>
00022 #include <limits.h>
00023 
00024 #include <libcvautomation/libcvautomation.h>
00025 
00026 void usage ();
00027 
00029 struct list {
00030     char *fileName;
00031     struct list *next;
00032 };
00033 
00034 typedef struct list basic_list; 
00036 
00037 int main( int argc, char** argv )
00038 {
00039     CvPoint result_point;
00040     result_point.x = result_point.y = 0;
00041 
00042     /* Set up everything for getopt */
00043     char *separator = ",";
00044     char *root_location = "root.png";
00045     char *sub_location = "sub.png";
00046     int tolerance = INT_MAX;
00047     int search_method = CV_TM_SQDIFF;
00048     int useX = 0; /* bool useX = false; */
00049     Bool useCenter = False;
00050     char *xDisplayLocation;
00051     Display *display;
00052     /* This line to suppress a compiler warning */
00053     display = NULL;
00054 
00055     /* Set the default display */
00056     xDisplayLocation = "";
00057 
00058     /* Set up the linked list for slave images */
00059     basic_list *list_head, *list_curr, *list_prev;
00060     list_head = list_curr = list_prev = NULL;
00061 
00062     /* Start getopt */
00063     while (1)
00064     {
00065         static struct option long_options[] =
00066         {
00067                 {"help",        no_argument,        0,  'h'},
00068                 {"usage",       no_argument,        0,  'u'},
00069                 {"version",     no_argument,        0,  'v'},
00070                 {"root-image",  required_argument,  0,  'r'},
00071                 {"sub-image",   required_argument,  0,  's'},
00072                 {"separator",   required_argument,  0,  'p'},
00073                 {"search-method",required_argument, 0,  'm'},
00074                 {"tolerance",   required_argument,  0,  't'},
00075                 {"x-root",      optional_argument,  0,  'x'},
00076                 {"center",      no_argument,        0,  'c'},
00077                 {"sane-tolerance", required_argument, 0, 'o'},
00078                 {0, 0, 0, 0}
00079         };
00080 
00081         int option_index = 0;
00082         opterr = 0;
00083 
00084         int c = getopt_long (argc, argv, "hur:s:p:m:t:x::c",
00085                             long_options, &option_index);
00086 
00087         /* We're done with parsing options */
00088         if (c == -1)
00089             break;
00090 
00091         switch (c)
00092         {
00093             case 0:
00094                 break;
00095 
00096             case 'h':
00097                 usage();
00098                 break;
00099 
00100             case 'u':
00101                 usage();
00102                 break;
00103 
00104             case 'v':
00105                 usage();
00106                 break;
00107 
00108             case 'r':
00109                 root_location = optarg;
00110                 break;
00111 
00112             case 's':
00113                 if ( list_head == NULL )
00114                 {
00115                     list_head = (basic_list *) malloc (sizeof(basic_list));
00116                     list_curr = list_head;
00117                 }
00118                 list_curr->fileName = optarg;
00119                 list_curr->next = (basic_list *) malloc (sizeof(basic_list));
00120                 list_curr->next->fileName = NULL;
00121                 list_curr = list_curr->next;
00122                 break;
00123 
00124             case 'p':
00125                 separator = optarg;
00126                 break;
00127 
00128             case 'm':
00129                 search_method = atoi(optarg);
00130                 break;
00131 
00132             case 't':
00133                 tolerance = atoi(optarg);
00134                 break;
00135 
00136             case 'x':
00137                 if ( optarg != NULL ) {
00138                     useX = 1;
00139                     xDisplayLocation = optarg;
00140                     display = XOpenDisplay(xDisplayLocation);
00141                 } else {
00142                     useX = 1;
00143                     xDisplayLocation = "";
00144                     display = XOpenDisplay(xDisplayLocation);
00145                 }
00146                 break;
00147 
00148             case 'c':
00149                 useCenter = True;
00150                 break;
00151 
00152             case 'o':
00153                 tolerance = atoi(optarg);
00154                 /* Provide a more sane way to configure tolerance:
00155                  * --sane-tolerance=100 ~= INT_MAX */
00156                 tolerance = pow(1.2397076, tolerance);
00157                 break;
00158 
00159             case '?':
00160                 /* Error routine */
00161                 break;
00162 
00163             default:
00164                 fprintf( stderr, "Unknown option..." );
00165                 exit(0);
00166         };
00167     }
00168 
00169     /* Make sure we have a linked list, 
00170      * and reset the linked list to go back through from the top */
00171     if ( list_head == NULL )
00172         return 1;
00173     else
00174         list_curr = list_head;
00175 
00176     do
00177     {
00178         sub_location = list_curr->fileName;
00179 
00180         if (useX && useCenter)
00181             result_point = matchSubImage_X11_location_center( display, sub_location, search_method, tolerance );
00182         else if (useX && !useCenter)
00183             result_point = matchSubImage_X11_location( display, sub_location, search_method, tolerance );
00184         else if (!useX && useCenter)
00185             result_point = matchSubImage_location_center( root_location, sub_location, search_method, tolerance );
00186         else /* if (!useX && !useCenter) */
00187             result_point = matchSubImage_location( root_location, sub_location, search_method, tolerance );
00188 
00189         if ( result_point.x != -1 && result_point.y != -1 )
00190             /* Output the match location */
00191             printf ("%s%s%i%s%i\n", list_curr->fileName, separator,
00192                     result_point.x, separator, result_point.y );
00193 
00194         /* With the way we allocate the list, we ensure that we always
00195          * have at least one element past the end of the list.
00196          * Also, deconstruct the list as we go. */
00197         list_prev = list_curr;
00198         list_curr = list_curr->next;
00199         free(list_prev);
00200 
00201     } while ( list_curr->fileName != NULL );
00202 
00203     /* And free the final element */
00204     free(list_curr);
00205 
00206     /* Clean up X */
00207     if (useX)
00208         XCloseDisplay(display);
00209 
00210     return 0;
00211 }
00212 
00213 /* 
00214  * ===  FUNCTION  ======================================================================
00215  *         Name:  usage
00216  *  Description:  I really shouldn't need to write this
00217  * =====================================================================================
00218  */
00219 void usage ( )
00220 {
00221     fprintf( stderr, "\
00222 Libcvautomation version: %s\n\
00223 cva-match -r <root_image> -s <sub_image> \n\
00224 cva-match -s <sub_image> -x \n\
00225 \n\
00226 This program uses OpenCV in order to recognize an image within an image.\n\
00227 The return code is how many matches were found - return 0 for no matches,\n\
00228 1 for one match, etc.\n\
00229 \n\
00230 Usage: \n\
00231 \n\
00232 \t-h, --help:\t\tDisplay this usage message.\n\
00233 \t-u, --usage:\t\tDisplay this usage message.\n\
00234 \t-r, --root-image:\tLocation of the root image to compare against.\n\
00235 \t-s, --sub-image:\tLocation of the sub-image to find in root.\n\
00236 \t-p, --separator:\tSeparator of the X and Y coordinates.\n\
00237 \t-t, --tolerance:\tSet how strict the match is - 100 is recommended lowest value.\n\
00238 \t\t\t\tNote: When using CCORR or CCOEFF tolerance works in opposite direction,\n\
00239 \t\t\t\tso -50 is recommended highest value.\n\
00240 \t-m, --search-method:\tSet which method is used to search for sub-images.\n\
00241 \t\t\t\tMethods:\n\
00242 \t\t\t\t\tCV_TM_SQDIFF = 0\n\
00243 \t\t\t\t\tCV_TM_SQDIFF_NORMED = 1\n\
00244 \t\t\t\t\tCV_TM_CCORR = 2\n\
00245 \t\t\t\t\tCV_TM_CCORR_NORMED = 3\n\
00246 \t\t\t\t\tCV_TM_CCOEFF = 4\n\
00247 \t\t\t\t\tCV_TM_COEFF_NORMED = 5\n\
00248 \t-x, --x-root[=DISPLAY]:\tSet the root image to come from X11\n\
00249 \t\t\t\tThe DISPLAY variable is optional, not specifying it will cause X\n\
00250 \t\t\t\tto use the default display (not specifically :0.0)\n\
00251 \t\t\t\tPlease note also that the '-x' must come at the end\n\
00252 \t\t\t\tsince it is an optional argument.\n\
00253 \t-c, --center:\t\tThe output points should be centered on the sub-image, rather\n\
00254 \t\t\t\tthan the top-left corner.\n\
00255 \t-o, --sane-tolerance:\tSet the tolerance using a scale of 1-100,\n\
00256 \t\t\t\trather than INT_MIN to INT_MAX (100 ~= INT_MAX)\n\
00257 \n\
00258 If you have any questions, comments, concerns, email <%s>\n", LIBCVAUTOMATION_VERSION, LIBCVAUTOMATION_BUGREPORT );
00259 
00260     exit (0);
00261 
00262 }       /* -----  end of function usage  ----- */
00263 
00264 /* Doxygen Information */
00271 /* The biggest purpose of documenting this code is to trick doxygen into making a man page for it. */
 All Classes Files Functions Defines