Changeset 98
- Timestamp:
- Apr 6, 2010, 11:38:23 AM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
liacs/MIR2010/SourceCode/main.cpp
r97 r98 6 6 #include <conio.h> 7 7 #include <iostream> 8 #include <iomanip> 9 #include <queue> 8 10 9 11 #include "cximage/ximage.h" 10 12 #include "xbrowseforfolder.h" 13 11 14 // function prototypes 12 15 bool CalculateDescriptors(const char *basedir); … … 15 18 bool DetermineWinterSportBatch(const char *basedir); 16 19 bool LoadAverages(const char *basedir); 20 bool ShowAverages(const char *basedir); 17 21 18 22 #define TRAINING_DIR_DEBUG "C:\\Documents and Settings\\rvdzwet\\Desktop\\liacs\\MIR2010\\trainingSet" 19 23 #define TESTSET_DIR_DEBUG "C:\\Documents and Settings\\rvdzwet\\Desktop\\liacs\\MIR2010\\testSet" 20 24 #define DEBUG 0 21 // number of bins to use for each color 22 // Note: number of bins must be a whole fraction of 256. if we would 23 // use 256 bins for each color then a single histogram would be 24 // 64MB, so we should choose a more sensible number 25 #define BIN_COUNT 32 26 27 // names of categories 25 26 // Names of categories (folders) 28 27 #define CATEGORY_SIZE 8 29 28 #define CATEGORY_1 "cat1.crowd" … … 36 35 #define CATEGORY_8 "opt5.curling" 37 36 38 const char *categories[CATEGORY_SIZE] = { CATEGORY_1, CATEGORY_2, CATEGORY_3, 39 CATEGORY_4, CATEGORY_5, CATEGORY_6, CATEGORY_7, CATEGORY_8}; 37 // Nicely concat into a string array 38 const char *categories[CATEGORY_SIZE] = { 39 CATEGORY_1, CATEGORY_2, CATEGORY_3, 40 CATEGORY_4, CATEGORY_5, CATEGORY_6, 41 CATEGORY_7, CATEGORY_8}; 42 43 // number of bins to use for each color 44 // Note: number of bins must be a whole fraction of 256. if we would 45 // use 256 bins for each color then a single histogram would be 46 // 64MB, so we should choose a more sensible number 47 #define BIN_COUNT 32 40 48 float average[CATEGORY_SIZE][BIN_COUNT*BIN_COUNT*BIN_COUNT]; 41 49 42 50 43 51 // Find common coloured shapes as characteristics 44 // Walk over image with SPREAD steps, if pixel -within TOLERANCE- matches previous pixel52 // Walk over image with opt_spread steps, if pixel -within opt_tolerance- matches previous pixel 45 53 // make the size of the specific block bigger. 46 #define TOLERANCE 20 47 #define SPREAD 20 48 #define MAX_SIZE 500 49 float average_block[CATEGORY_SIZE][MAX_SIZE/SPREAD]; 54 // Block '0' is used an non-matcher. Not taken into account for the time beeing. 55 int opt_tolerance = 10; 56 int opt_spread = 20; 57 #define MAX_BLOCKSIZE 500 58 float average_block[CATEGORY_SIZE][MAX_BLOCKSIZE]; 50 59 51 60 … … 54 63 #define _return(err_msg, retval) printf("DEBUG: %s\n",err_msg); cin.get(); return(retval); 55 64 #define cout_status(msg,flag) cout << msg; (flag) ? cout << " off" : cout << " on"; cout << endl; 56 57 65 #define cout_point(x,y) "[" << x << "," << y << "]" 66 67 // Default options 68 bool opt_debug = false; 58 69 bool opt_verbose = false; 59 bool opt_histogram = true;70 bool opt_histogram = false; 60 71 bool opt_block = true; 61 72 … … 92 103 if (strlen(dbdir) == 0) 93 104 return 0; 94 if (XBrowseForFolder(NULL, "Please select image testset folder", NULL, testdir, sizeof(testdir)) == FALSE)105 if (XBrowseForFolder(NULL, "Please select image testset batch folder, could be any folder", NULL, testdir, sizeof(testdir)) == FALSE) 95 106 return 0; 96 107 if (strlen(testdir) == 0) … … 126 137 cout << endl; 127 138 cout << "1. calculate descriptors" << endl; 128 cout << "2. categorize descriptors (aka averages histograms)" << endl;129 cout << "3. determine winter sport " << endl;139 cout << "2. categorize descriptors (aka averages)" << endl; 140 cout << "3. determine winter sport on single image" << endl; 130 141 cout << "4. batch test winter sport" << endl; 142 cout << "9. Show averages" << endl; 143 cout << endl; 144 cout_status("d. Turn debug mode", opt_debug); 131 145 cout_status("v. Turn verbose mode", opt_verbose); 132 146 cout_status("h. Turn histogram classifier", opt_histogram); 133 cout_status("b. Turn block classifier", opt_block); 134 147 cout_status("b. Turn block classifier", opt_block); 135 148 cout << endl; 149 cout << "==== Parameters Block Classifier ====" << endl; 150 cout << "s. Set spread [currently: " << opt_spread << "]" << endl; 151 cout << "t. Set Tolerance [currently: " << opt_tolerance << "]" << endl; 152 136 153 cout << "Please select option, or type 'q' to quit: "; 137 154 char c = _getch(); … … 171 188 } 172 189 break; 190 case '9': 191 if (!LoadAverages(dbdir)){ 192 _return("Unable to load averages",1); 193 } 194 if (!ShowAverages(testdir)) { 195 _return("Unable to show averages",1); 196 } 197 break; 198 case 'd': 199 opt_debug = (!opt_debug); 200 break; 173 201 case 'v': 174 202 opt_verbose = (!opt_verbose); … … 180 208 opt_histogram = (!opt_histogram); 181 209 break; 210 case 's': 211 cout << "Spread value: "; 212 cin >> opt_spread; 213 cout << "WARNING: Make sure to re-classify before (Batch)Testing" << endl; 214 cout << "Any key to continue..." << endl; cin.get(); 215 break; 216 case 't': 217 cout << "Tolerance value: "; 218 cin >> opt_tolerance; 219 cout << "WARNING: Make sure to re-classify before (Batch)Testing" << endl; 220 cout << "Any key to continue..." << endl; cin.get(); 221 break; 222 182 223 default: 183 224 continue; … … 228 269 } 229 270 271 struct point { 272 int x; 273 int y; 274 }; 275 276 230 277 // histogram should be a preallocated array of size BIN_COUNT*BIN_COUNT*BIN_COUNT elements and will 231 278 // be filled with the color histogram of the image where path points at … … 236 283 if (!image.IsValid()) 237 284 return false; 285 238 286 // clear histogram 239 memset(block, 0, MAX_SIZE/SPREAD * sizeof(float)); 287 memset(block, 0, MAX_BLOCKSIZE * sizeof(float)); 288 240 289 // walk through the pixels to fill the histogram 241 290 const int width = (int)image.GetWidth(); 242 291 const int height = (int)image.GetHeight(); 243 292 244 int rgb_value = 0; 245 int rgb_prev = 0; 246 293 int * status = new int [width * height]; 294 //memset(status,0, width * height * sizeof(int)); 295 296 queue<point> queue; 297 int rgb_current, rgb_right, rgb_up = 0; 247 298 int block_size = 0; 248 249 for (int y = 0; y < height; y += SPREAD) 250 { 251 for (int x = 0; x < width; x += SPREAD) 299 point p, p_right, p_up; 300 301 RGBQUAD rgb; 302 303 // Pixel field status 304 // 0 = No need for processing 305 // 1 = Need processing 306 // 2 = Done processing 307 for (int x = 0; x < width; x += opt_spread) 308 for (int y = 0; y < height; y += opt_spread) 309 status[x * height + y] = 1; 310 311 for (int x = 0; x < width; x += opt_spread) 312 { 313 for (int y = 0; y < height; y += opt_spread) 252 314 { 253 // Note: CxImage library starts counting at lower-left corner of the image, 254 // which is seen as the top of the image. 255 RGBQUAD rgb = image.BlindGetPixelColor(x, y, false); 256 rgb_value = (rgb.rgbRed + rgb.rgbBlue + rgb.rgbGreen); 257 258 if (abs(rgb_value - rgb_prev) > TOLERANCE) { 259 block[block_size]++; 260 block_size = 1; 261 } 262 rgb_prev = rgb_value; 263 } 264 } 315 // Only process if required to and not yet done 316 if (status[x * height + y] != 1) { 317 if (opt_debug) 318 cout << "Already processed point " << cout_point(x,y) << endl; 319 continue; 320 } 321 322 if(opt_debug) 323 cout << "Testing new point " << cout_point(x,y) << endl; 324 325 // Stack based expantion and evaluation 326 block_size = 0; 327 p.x = x; 328 p.y = y; 329 queue.push(p); 330 331 while (!queue.empty()) 332 { 333 // Note: CxImage library starts counting at lower-left corner of the image 334 // which is seen as the top of the image. 335 p = queue.front(); 336 queue.pop(); 337 338 // Make sure not to process points twice 339 if (status[p.x * height + p.y] != 1) 340 continue; 341 342 if (opt_debug) 343 cout << "Processing point " << cout_point(p.x,p.y) << endl; 344 345 rgb = image.BlindGetPixelColor(p.x, p.y, false); 346 rgb_current = (rgb.rgbRed + rgb.rgbBlue + rgb.rgbGreen); 347 348 p_right.x = p.x + opt_spread; 349 p_right.y = p.y; 350 351 // Check if right one fits the bill 352 if (p_right.x < width) 353 { 354 rgb = image.BlindGetPixelColor(p_right.x, p_right.y, false); 355 rgb_right = (rgb.rgbRed + rgb.rgbBlue + rgb.rgbGreen); 356 357 if (abs(rgb_right - rgb_current) < opt_tolerance) 358 { 359 if (opt_debug) 360 cout << "Right point " << cout_point(p_right.x,p_right.y) << " gets included in block" << endl; 361 362 block_size++; 363 queue.push(p_right); 364 } 365 } 366 367 // Check if up one fits the bill 368 p_up.x = p.x; 369 p_up.y = p.y + opt_spread; 370 if (p_up.y < height) 371 { 372 rgb = image.BlindGetPixelColor(p_up.x, p_up.y, false); 373 rgb_up = (rgb.rgbRed + rgb.rgbBlue + rgb.rgbGreen); 374 375 if (abs(rgb_up - rgb_current) < opt_tolerance) 376 { 377 if (opt_debug) 378 cout << "Upper point " << cout_point(p_up.x, p_up.y) << " gets included in block" << endl; 379 380 block_size++; 381 queue.push(p_up); 382 } 383 } 384 status[p.x * height + p.y] = 2; 385 } 386 if (opt_debug) 387 cout << cout_point(x,y) << " blocksize " << block_size << endl; 388 if (block_size > MAX_BLOCKSIZE) { 389 cout << "WARN: block_size larger than fixed limit of " << MAX_BLOCKSIZE << endl; 390 block_size = MAX_BLOCKSIZE; 391 } 392 393 block[block_size]++; 394 } 395 } 396 397 delete status; 265 398 return true; 266 399 } … … 270 403 // the histogram that we reuse for each image 271 404 float *histogram = new float[BIN_COUNT*BIN_COUNT*BIN_COUNT]; 272 float *block = new float[MAX_ SIZE/SPREAD];405 float *block = new float[MAX_BLOCKSIZE]; 273 406 // walk through all images 274 407 // Note: each of the three categories has 50 images … … 304 437 if (fwrite(histogram, sizeof(float), BIN_COUNT*BIN_COUNT*BIN_COUNT, file) != BIN_COUNT*BIN_COUNT*BIN_COUNT) 305 438 goto failure; 306 if (fwrite(block, sizeof(float), MAX_ SIZE/SPREAD, file) != MAX_SIZE/SPREAD)439 if (fwrite(block, sizeof(float), MAX_BLOCKSIZE, file) != MAX_BLOCKSIZE) 307 440 goto failure; 308 441 SAFE_CLOSEFILE(file); … … 328 461 // characteristics of that category 329 462 float *histogram = new float[BIN_COUNT*BIN_COUNT*BIN_COUNT]; 330 float *block = new float[MAX_ SIZE/SPREAD];331 float *average_block = new float[MAX_ SIZE/SPREAD];463 float *block = new float[MAX_BLOCKSIZE]; 464 float *average_block = new float[MAX_BLOCKSIZE]; 332 465 float *average = new float[BIN_COUNT*BIN_COUNT*BIN_COUNT]; 333 466 // walk through all descriptors … … 362 495 goto failure; 363 496 } 364 if (fread(block, sizeof(float), MAX_ SIZE/SPREAD, file) != MAX_SIZE/SPREAD) {497 if (fread(block, sizeof(float), MAX_BLOCKSIZE, file) != MAX_BLOCKSIZE) { 365 498 p_err("Cannot read block"); 366 499 goto failure; … … 372 505 average[b] += histogram[b]; 373 506 374 for (int b = 0; b < MAX_ SIZE/SPREAD; b++)507 for (int b = 0; b < MAX_BLOCKSIZE; b++) 375 508 average_block[b] += block[b]; 376 509 … … 380 513 for (int b = 0; b < BIN_COUNT*BIN_COUNT*BIN_COUNT; b++) 381 514 average[b] /= c_size; 382 383 for (int b = 0; b < MAX_ SIZE/SPREAD; b++)515 516 for (int b = 0; b < MAX_BLOCKSIZE; b++) 384 517 average_block[b] /= c_size; 385 518 … … 390 523 if (fwrite(average, sizeof(float), BIN_COUNT*BIN_COUNT*BIN_COUNT, file) != BIN_COUNT*BIN_COUNT*BIN_COUNT) 391 524 goto failure; 392 if (fwrite(average_block, sizeof(float), MAX_ SIZE/SPREAD, file) != MAX_SIZE/SPREAD)525 if (fwrite(average_block, sizeof(float), MAX_BLOCKSIZE, file) != MAX_BLOCKSIZE) 393 526 goto failure; 394 527 … … 428 561 if (fread(average[c], sizeof(float), BIN_COUNT*BIN_COUNT*BIN_COUNT, file) != BIN_COUNT*BIN_COUNT*BIN_COUNT) 429 562 return false; 430 if (fread(average_block[c], sizeof(float), MAX_ SIZE/SPREAD, file) != MAX_SIZE/SPREAD)563 if (fread(average_block[c], sizeof(float), MAX_BLOCKSIZE, file) != MAX_BLOCKSIZE) 431 564 return false; 432 565 … … 436 569 } 437 570 571 572 bool ShowAverages(const char *basedir) { 573 574 if (opt_histogram) { 575 cout << "Histogram averages" << endl; 576 for (int c = 0; c < CATEGORY_SIZE; c++) { 577 cout << "Category [" << categories[c] << "] " << endl; 578 for (int i = 1; i <= BIN_COUNT*BIN_COUNT*BIN_COUNT; i++) { 579 cout << fixed << setprecision(2) << average[c][i-1] << " "; 580 if ((i % 10) == 0) cout << endl; 581 } 582 cout << endl; 583 } 584 } 585 if (opt_block) { 586 cout << "Block averages" << endl; 587 for (int c = 0; c < CATEGORY_SIZE; c++) { 588 cout << "Category [" << categories[c] << "] " << endl; 589 for (int i = 1; i < MAX_BLOCKSIZE; i++) { 590 cout << fixed << setprecision(2) << average_block[c][i-1] << " "; 591 if ((i % 10) == 0) cout << endl; 592 } 593 cout << endl; 594 595 } 596 } 597 return true; 598 } 438 599 int DetermineCategory(const char *path, const int guess=-1, const bool verbose=false) { 439 600 float *histogram = new float[BIN_COUNT*BIN_COUNT*BIN_COUNT]; 440 float *block = new float[MAX_ SIZE/SPREAD];601 float *block = new float[MAX_BLOCKSIZE]; 441 602 float cat2dist[CATEGORY_SIZE]; 442 603 float cat2block[CATEGORY_SIZE]; … … 462 623 cat2dist[c] += fabs(histogram[b] - average[c][b]); 463 624 464 for (int b = 0; b < MAX_SIZE/SPREAD; b++) 625 /* No including of the non-matching points currently */ 626 for (int b = 1; b < MAX_BLOCKSIZE; b++) 465 627 cat2block[c] += fabs(block[b] - average_block[c][b]); 466 628 } … … 498 660 return cat_block; 499 661 } else { 500 662 return -1; 501 663 } 502 664 } … … 560 722 catname = categories[c]; 561 723 sprintf(catdir, "%s\\%s\\", basedir, catname); 562 724 563 725 /* process the images in the directory */ 564 726 for (int i = 1; i <= 50; i++) … … 581 743 cout << "[" << catname << "] results " << c_succes[c] << "/" << c_total[c] << endl; 582 744 } 583 745 584 746 /* Display grand total */ 585 747 cout << "=== Totals ===" << endl; … … 598 760 all_succes += c_succes[c]; 599 761 } 600 printf ("[%-20s] %i/%i\n","total",all_succes,all_ succes);762 printf ("[%-20s] %i/%i\n","total",all_succes,all_total); 601 763 cout << "Press any key to continue..."; cin.get(); 602 764
Note:
See TracChangeset
for help on using the changeset viewer.