libcvautomation
1.2
|
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. */