source: liacs/MIR2010/SourceCode/main.cpp@ 98

Last change on this file since 98 was 98, checked in by Rick van der Zwet, 15 years ago
  • Parameters
  • menu options
  • pointer exceptions fixed


TODO:

  • averages are still not right
File size: 21.9 KB
RevLine 
[96]1// main.cpp : Defines the entry point for the console application.
2//
3
4#include "config.h"
5#include <commdlg.h>
6#include <conio.h>
7#include <iostream>
[98]8#include <iomanip>
9#include <queue>
[96]10
11#include "cximage/ximage.h"
12#include "xbrowseforfolder.h"
[98]13
[96]14// function prototypes
15bool CalculateDescriptors(const char *basedir);
16bool CategorizeDescriptors(const char *basedir);
17bool DetermineWinterSportSelect();
18bool DetermineWinterSportBatch(const char *basedir);
19bool LoadAverages(const char *basedir);
[98]20bool ShowAverages(const char *basedir);
[96]21
22#define TRAINING_DIR_DEBUG "C:\\Documents and Settings\\rvdzwet\\Desktop\\liacs\\MIR2010\\trainingSet"
23#define TESTSET_DIR_DEBUG "C:\\Documents and Settings\\rvdzwet\\Desktop\\liacs\\MIR2010\\testSet"
24#define DEBUG 0
25
[98]26// Names of categories (folders)
[96]27#define CATEGORY_SIZE 8
28#define CATEGORY_1 "cat1.crowd"
29#define CATEGORY_2 "cat2.skijump"
30#define CATEGORY_3 "cat3.snowboarding"
31#define CATEGORY_4 "opt1.bobsleigh"
32#define CATEGORY_5 "opt2.icehockey"
33#define CATEGORY_6 "opt3.speedskating"
34#define CATEGORY_7 "opt4.downhillski"
35#define CATEGORY_8 "opt5.curling"
36
[98]37// Nicely concat into a string array
38const 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
[96]48float average[CATEGORY_SIZE][BIN_COUNT*BIN_COUNT*BIN_COUNT];
49
[97]50
51// Find common coloured shapes as characteristics
[98]52// Walk over image with opt_spread steps, if pixel -within opt_tolerance- matches previous pixel
[97]53// make the size of the specific block bigger.
[98]54// Block '0' is used an non-matcher. Not taken into account for the time beeing.
55int opt_tolerance = 10;
56int opt_spread = 20;
57#define MAX_BLOCKSIZE 500
58float average_block[CATEGORY_SIZE][MAX_BLOCKSIZE];
[97]59
60
[96]61// Some prototyping foo on functions
[97]62#define p_err(err_msg) printf("ERROR: %s\n", err_msg);
[96]63#define _return(err_msg, retval) printf("DEBUG: %s\n",err_msg); cin.get(); return(retval);
[97]64#define cout_status(msg,flag) cout << msg; (flag) ? cout << " off" : cout << " on"; cout << endl;
[98]65#define cout_point(x,y) "[" << x << "," << y << "]"
[96]66
[98]67// Default options
68bool opt_debug = false;
[97]69bool opt_verbose = false;
[98]70bool opt_histogram = false;
[97]71bool opt_block = true;
72
[96]73bool file_exists(const char * filename)
74{
75 if (FILE * file = fopen(filename, "r"))
76 {
77 fclose(file);
78 return true;
79 }
80 return false;
81}
82
83
84int main(int argc, char **argv)
85{
86 char dbdir[MAX_PATH];
87 char testdir[MAX_PATH];
88
89#if defined(TRAINING_DIR_DEBUG)
90 if (strcpy_s(dbdir, TRAINING_DIR_DEBUG) != 0) {
91 _return("Cannot copy TRAINING_DIR_DEBUG",1);
92 }
93 if (strcpy_s(testdir, TESTSET_DIR_DEBUG) != 0) {
94 _return("Cannot copy TESTSET_DIR_DEBUG",2);
95 }
96#else
97 // ask the user for the image database
98 // in the image directory, the images are stored in categorized
99 // folders. store the descriptors we calculate in the same
100 // folder as the image
101 if (XBrowseForFolder(NULL, "Please select image database folder", NULL, dbdir, sizeof(dbdir)) == FALSE)
102 return 0;
103 if (strlen(dbdir) == 0)
104 return 0;
[98]105 if (XBrowseForFolder(NULL, "Please select image testset batch folder, could be any folder", NULL, testdir, sizeof(testdir)) == FALSE)
[96]106 return 0;
107 if (strlen(testdir) == 0)
108 return 0;
109
110#endif
111
112#if DEBUG
113 if (!LoadAverages(dbdir)){
114 _return("Unable to load averages",1);
115 }
116
117 if (!DetermineWinterSportBatch(testdir)) {
118 _return("could not run winter sport batch",1);
119 }
120 return(0);
121#endif
122
123 // ask the user which option to use
124 while (true)
125 {
126 //system("cls");
127 cout << "Using database directory: " << dbdir << endl;
128 cout << "Using test directory: " << testdir << endl;
129 cout << "Using categories: " << endl;
130 for (int i = 0; i < CATEGORY_SIZE; i++)
131 {
132 cout << " - " << categories[i] << endl;
133 }
134 cout << "***************************" << endl;
135 cout << "* Winter Olympic Imagery *" << endl;
136 cout << "***************************" << endl;
137 cout << endl;
138 cout << "1. calculate descriptors" << endl;
[98]139 cout << "2. categorize descriptors (aka averages)" << endl;
140 cout << "3. determine winter sport on single image" << endl;
[96]141 cout << "4. batch test winter sport" << endl;
[98]142 cout << "9. Show averages" << endl;
143 cout << endl;
144 cout_status("d. Turn debug mode", opt_debug);
[97]145 cout_status("v. Turn verbose mode", opt_verbose);
146 cout_status("h. Turn histogram classifier", opt_histogram);
[98]147 cout_status("b. Turn block classifier", opt_block);
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;
[97]152
[96]153 cout << "Please select option, or type 'q' to quit: ";
154 char c = _getch();
155 cout << c << endl;
156 fflush(stdin);
157 // start the chosen option
158 switch (c)
[97]159 {
[96]160 case 'q':
161 return 0;
162 case '1':
163 if (!CalculateDescriptors(dbdir)) {
164 _return("could not calculate descriptors",1);
165 }
166 break;
167 case '2':
168 if (!CategorizeDescriptors(dbdir)){
169 _return("could not categorize descriptors",1);
170 }
171 break;
172 case '3':
173 if (!LoadAverages(dbdir)){
174 _return("Unable to load averages",1);
175 }
176
177 if (!DetermineWinterSportSelect()){
178 _return("could not determine winter sport",1);
179 }
180 break;
181 case '4':
182 if (!LoadAverages(dbdir)){
183 _return("Unable to load averages",1);
184 }
185
186 if (!DetermineWinterSportBatch(testdir)) {
187 _return("could not run winter sport batch",1);
188 }
189 break;
[98]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;
[96]201 case 'v':
[97]202 opt_verbose = (!opt_verbose);
203 break;
204 case 'b':
205 opt_block = (!opt_block);
206 break;
207 case 'h':
208 opt_histogram = (!opt_histogram);
209 break;
[98]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
[96]223 default:
224 continue;
225 }
226 }
227 return 0;
228}
229
230// histogram should be a preallocated array of size BIN_COUNT*BIN_COUNT*BIN_COUNT elements and will
231// be filled with the color histogram of the image where path points at
232bool CalculateDescriptor(const char *path, float *histogram)
233{
234 // load the image
235 CxImage image(path, CXIMAGE_FORMAT_JPG);
236 if (!image.IsValid())
237 return false;
238 // clear histogram
239 memset(histogram, 0, BIN_COUNT*BIN_COUNT*BIN_COUNT * sizeof(float));
240 // walk through the pixels to fill the histogram
241 int width = (int)image.GetWidth();
242 int height = (int)image.GetHeight();
243 int bin_r, bin_g, bin_b;
244 for (int y = 0; y < height; y++)
245 {
246 for (int x = 0; x < width; x++)
247 {
248 // Note: CxImage library starts counting at lower-left corner of the image,
249 // which is seen as the top of the image. however, usually images
250 // start counting from the top-left corner of the image. thus if you
251 // want to get pixel(2, 2) from the top-left you would have to ask
252 // for pixel (2, height - 2 - 1) from CxImage. although in this
253 // situation we don't care which pixel is where, we only care about
254 // its color.
255 RGBQUAD rgb = image.BlindGetPixelColor(x, y, false);
256 // determine the bin this color falls in
257 bin_r = rgb.rgbRed / (256 / BIN_COUNT);
258 bin_g = rgb.rgbGreen / (256 / BIN_COUNT);
259 bin_b = rgb.rgbBlue / (256 / BIN_COUNT);
260 histogram[bin_r*BIN_COUNT*BIN_COUNT + bin_g*BIN_COUNT + bin_b]++;
261 }
262 }
263 // normalize the histogram so that all together the values will add up
264 // to one. since there are width * height pixels, we divide each value
265 // by this amount
266 for (int i = 0; i < BIN_COUNT*BIN_COUNT*BIN_COUNT; i++)
267 histogram[i] /= width * height;
268 return true;
269}
270
[98]271struct point {
272 int x;
273 int y;
274};
275
276
[97]277// histogram should be a preallocated array of size BIN_COUNT*BIN_COUNT*BIN_COUNT elements and will
278// be filled with the color histogram of the image where path points at
279bool CalculateBlock(const char *path, float *block)
280{
281 // load the image
282 CxImage image(path, CXIMAGE_FORMAT_JPG);
283 if (!image.IsValid())
284 return false;
[98]285
[97]286 // clear histogram
[98]287 memset(block, 0, MAX_BLOCKSIZE * sizeof(float));
288
[97]289 // walk through the pixels to fill the histogram
290 const int width = (int)image.GetWidth();
291 const int height = (int)image.GetHeight();
292
[98]293 int * status = new int [width * height];
294 //memset(status,0, width * height * sizeof(int));
[97]295
[98]296 queue<point> queue;
297 int rgb_current, rgb_right, rgb_up = 0;
[97]298 int block_size = 0;
[98]299 point p, p_right, p_up;
[97]300
[98]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)
[97]312 {
[98]313 for (int y = 0; y < height; y += opt_spread)
[97]314 {
[98]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 }
[97]321
[98]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;
[97]385 }
[98]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]++;
[97]394 }
395 }
[98]396
397 delete status;
[97]398 return true;
399}
400
[96]401bool CalculateDescriptors(const char *basedir)
402{
403 // the histogram that we reuse for each image
404 float *histogram = new float[BIN_COUNT*BIN_COUNT*BIN_COUNT];
[98]405 float *block = new float[MAX_BLOCKSIZE];
[96]406 // walk through all images
407 // Note: each of the three categories has 50 images
408 char path[MAX_PATH];
409 char catdir[MAX_PATH];
410 const char *catname;
411 FILE *file = NULL;
412 for (int c = 0; c < CATEGORY_SIZE; c++)
413 {
414 catname = categories[c];
415 sprintf(catdir, "%s\\%s\\", basedir, catname);
416 cout << "[" << catname << "] Using directory " << catdir << endl;
417
418 // process the images in the directory
419 for (int i = 1; i <= 50; i++)
420 {
421 SAFE_SPRINTF(path, sizeof(path), "%s%i.jpg", catdir, i);
422 if (!file_exists(path)) {
423 continue;
424 }
425 cout << "[" << catname << "] processing image " << i << endl;
426 // calculate the histogram descriptor
427 if (!CalculateDescriptor(path, histogram))
428 goto failure;
[97]429
430 if (!CalculateBlock(path, block))
431 goto failure;
432
433 // save the descriptor,block to disk
[96]434 SAFE_SPRINTF(path, sizeof(path), "%s%i.dat", catdir, i);
435 if ((file = fopen(path, "wb")) == NULL)
436 goto failure;
437 if (fwrite(histogram, sizeof(float), BIN_COUNT*BIN_COUNT*BIN_COUNT, file) != BIN_COUNT*BIN_COUNT*BIN_COUNT)
438 goto failure;
[98]439 if (fwrite(block, sizeof(float), MAX_BLOCKSIZE, file) != MAX_BLOCKSIZE)
[97]440 goto failure;
[96]441 SAFE_CLOSEFILE(file);
[97]442
443
[96]444 }
445 }
446 // release resources
447 SAFE_DELETE_ARRAY(histogram);
[97]448 SAFE_DELETE_ARRAY(block);
[96]449 return true;
450
451failure:
452 SAFE_CLOSEFILE(file);
453 SAFE_DELETE_ARRAY(histogram);
[97]454 SAFE_DELETE_ARRAY(block);
[96]455 return false;
456}
457
458bool CategorizeDescriptors(const char *basedir)
459{
460 // analyze the descriptors per category to determine the
461 // characteristics of that category
462 float *histogram = new float[BIN_COUNT*BIN_COUNT*BIN_COUNT];
[98]463 float *block = new float[MAX_BLOCKSIZE];
464 float *average_block = new float[MAX_BLOCKSIZE];
[96]465 float *average = new float[BIN_COUNT*BIN_COUNT*BIN_COUNT];
466 // walk through all descriptors
467 char path[MAX_PATH];
468 char catdir[MAX_PATH];
469 const char *catname;
470 FILE *file = NULL;
471 int c_size = 0;
472 for (int c = 0; c < CATEGORY_SIZE; c++)
473 {
474 c_size = 0;
475 catname = categories[c];
476 sprintf(catdir,"%s\\%s\\", basedir, catname);
477
478 // average all descriptors
479 memset(average, 0, BIN_COUNT*BIN_COUNT*BIN_COUNT * sizeof(float));
480 for (int i = 1; i <= 50; i++)
481 {
482 SAFE_SPRINTF(path, sizeof(path), "%s%i.dat", catdir, i);
483 if (!file_exists(path)) {
[97]484 p_err("File does not exists");
[96]485 continue;
486 }
487 cout << "[" << catname << "] processing image " << i << endl;
488 // load the histogram descriptor
[97]489 if ((file = fopen(path, "rb")) == NULL) {
490 p_err("Cannot open average datafile");
[96]491 goto failure;
[97]492 }
493 if (fread(histogram, sizeof(float), BIN_COUNT*BIN_COUNT*BIN_COUNT, file) != BIN_COUNT*BIN_COUNT*BIN_COUNT) {
494 p_err("Cannot read histogram");
[96]495 goto failure;
[97]496 }
[98]497 if (fread(block, sizeof(float), MAX_BLOCKSIZE, file) != MAX_BLOCKSIZE) {
[97]498 p_err("Cannot read block");
499 goto failure;
500 }
501
[96]502 SAFE_CLOSEFILE(file);
503 // add the value of each bin to the average
504 for (int b = 0; b < BIN_COUNT*BIN_COUNT*BIN_COUNT; b++)
505 average[b] += histogram[b];
506
[98]507 for (int b = 0; b < MAX_BLOCKSIZE; b++)
[97]508 average_block[b] += block[b];
509
[96]510 c_size++;
511 }
512
513 for (int b = 0; b < BIN_COUNT*BIN_COUNT*BIN_COUNT; b++)
514 average[b] /= c_size;
[98]515
516 for (int b = 0; b < MAX_BLOCKSIZE; b++)
[97]517 average_block[b] /= c_size;
518
[96]519 // save the average to disk
520 SAFE_SPRINTF(path, sizeof(path), "%s%s.dat", catdir, "average");
521 if ((file = fopen(path, "wb")) == NULL)
522 goto failure;
523 if (fwrite(average, sizeof(float), BIN_COUNT*BIN_COUNT*BIN_COUNT, file) != BIN_COUNT*BIN_COUNT*BIN_COUNT)
524 goto failure;
[98]525 if (fwrite(average_block, sizeof(float), MAX_BLOCKSIZE, file) != MAX_BLOCKSIZE)
[97]526 goto failure;
527
[96]528 SAFE_CLOSEFILE(file);
529 }
530 // release resources
531 SAFE_DELETE_ARRAY(histogram);
532 SAFE_DELETE_ARRAY(average);
[97]533 SAFE_DELETE_ARRAY(block);
[96]534 return true;
535
536failure:
537 SAFE_CLOSEFILE(file);
538 SAFE_DELETE_ARRAY(histogram);
[97]539 SAFE_DELETE_ARRAY(block);
[96]540 return false;
541}
542
543bool LoadAverages(const char *basedir) {
544 /* determine the distance to each category */
545 const char *catname;
546 char catdir[MAX_PATH];
547 char path[MAX_PATH];
548 FILE *file = NULL;
549
550 for (int c = 0; c < CATEGORY_SIZE; c++)
551 {
552 catname = categories[c];
553 sprintf(catdir, "%s\\%s\\", basedir, catname);
554
555 // load the average from disk
556 SAFE_SPRINTF(path, sizeof(path), "%s%s.dat", catdir, "average");
557 if ((file = fopen(path, "rb")) == NULL) {
558 cout << "Cannot open " << path << endl;
559 return false;
560 }
561 if (fread(average[c], sizeof(float), BIN_COUNT*BIN_COUNT*BIN_COUNT, file) != BIN_COUNT*BIN_COUNT*BIN_COUNT)
562 return false;
[98]563 if (fread(average_block[c], sizeof(float), MAX_BLOCKSIZE, file) != MAX_BLOCKSIZE)
[97]564 return false;
565
[96]566 SAFE_CLOSEFILE(file);
567 }
568 return true;
569}
570
[98]571
572bool 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}
[97]599int DetermineCategory(const char *path, const int guess=-1, const bool verbose=false) {
[96]600 float *histogram = new float[BIN_COUNT*BIN_COUNT*BIN_COUNT];
[98]601 float *block = new float[MAX_BLOCKSIZE];
[96]602 float cat2dist[CATEGORY_SIZE];
[97]603 float cat2block[CATEGORY_SIZE];
[96]604
605 /* First category default best canidate */
[97]606 int cat_histogram = 0;
607 int cat_block = 0;
[96]608
609 /* calculate the histogram of the image */
610 if (!CalculateDescriptor(path, histogram))
611 return -1;
612
[97]613 if (!CalculateBlock(path, block))
614 return -1;
615
[96]616 /* determine the distance to each category */
617 for (int c = 0; c < CATEGORY_SIZE; c++)
618 {
619 // determine distance
620 cat2dist[c] = 0.0f;
[97]621 cat2block[c] = 0.0f;
[96]622 for (int b = 0; b < BIN_COUNT*BIN_COUNT*BIN_COUNT; b++)
623 cat2dist[c] += fabs(histogram[b] - average[c][b]);
[97]624
[98]625 /* No including of the non-matching points currently */
626 for (int b = 1; b < MAX_BLOCKSIZE; b++)
[97]627 cat2block[c] += fabs(block[b] - average_block[c][b]);
[96]628 }
629
630 /* determine the winning category */
[97]631 for (int i = 1; i < CATEGORY_SIZE; i++) {
632 if (cat2dist[i] < cat2dist[cat_histogram])
633 cat_histogram = i;
634 if (cat2block[i] < cat2block[cat_block])
635 cat_block = i;
636 }
[96]637
638 if (verbose) {
639 /* Dirty hack to show some more details in case of failure */
[97]640 if (opt_histogram && guess != -1 && guess != cat_histogram) {
[96]641 for (int i = 0; i < CATEGORY_SIZE; i++) {
[97]642 printf("%s [histogram] distance to %-20s: %f %s\n", (cat_histogram == i) ? "*" : " ",
643 categories[i], cat2dist[i],(cat_histogram == i) ? "*" : "");
[96]644 }
645 }
[97]646 if (opt_block && guess != -1 && guess != cat_block) {
647 for (int i = 0; i < CATEGORY_SIZE; i++) {
648 printf("%s [block] distance to %-20s: %f %s\n", (cat_block == i) ? "*" : " ",
649 categories[i], cat2block[i],(cat_block == i) ? "*" : "");
650 }
651 }
652
[96]653 }
654
655 /* return result */
[97]656 if (opt_histogram) {
657 return cat_histogram;
658 }
659 else if (opt_block) {
660 return cat_block;
661 } else {
[98]662 return -1;
[97]663 }
[96]664}
665
666/* ask for an input image and determine the most likely
667* category it belongs to
668*/
669bool DetermineWinterSportSelect()
670{
671 float *histogram = new float[BIN_COUNT*BIN_COUNT*BIN_COUNT];
672 char path[MAX_PATH] = {0};
673 char catdir[MAX_PATH] = {0};
674 const char *catname = NULL;
675 FILE *file = NULL;
676 int c = NULL;
677 float cat2dist[CATEGORY_SIZE] = {0};
678
679 OPENFILENAME ofn = {0};
680 //ofn.lpstrFilter = "Image files\0*.jpg;*.png;*.bmp\0\0";
681 ofn.lpstrFilter = "Image files\0*.jpg\0\0";
682 ofn.lpstrFile = path;
683 ofn.nMaxFile = MAX_PATH;
684 ofn.lpstrTitle = "Choose image file";
685 ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
686 ofn.lStructSize = sizeof(OPENFILENAME);
687
688 if (GetOpenFileName(&ofn) == FALSE)
689 goto failure;
690
691 if ((c = DetermineCategory(path,-2)) == -1)
692 return false;
693
694 cout << "The category this image belongs is category: " << categories[c] << " [" << c << "]" << endl;
695 cout << "Press any key to continue... ";
696 _getch();
697 fflush(stdin);
698 // release resources
699 SAFE_DELETE_ARRAY(histogram);
700 return true;
701
702failure:
703 SAFE_CLOSEFILE(file);
704 SAFE_DELETE_ARRAY(histogram);
705 return false;
706}
707
708bool DetermineWinterSportBatch(const char *basedir)
709{
710 const char *catname;
711 char catdir[MAX_PATH];
712 char path[MAX_PATH];
713
714 int all_total = 0;
715 int all_succes = 0;
716 int c_total[CATEGORY_SIZE] = {0};
717 int c_succes[CATEGORY_SIZE] = {0};
718
719 /* determine the distance to each category */
720 for (int c = 0; c < CATEGORY_SIZE; c++)
721 {
722 catname = categories[c];
723 sprintf(catdir, "%s\\%s\\", basedir, catname);
[98]724
[96]725 /* process the images in the directory */
726 for (int i = 1; i <= 50; i++)
727 {
728 SAFE_SPRINTF(path, sizeof(path), "%s%i.jpg", catdir, i);
729 if (!file_exists(path)) {
730 continue;
731 }
732
733 c_total[c]++;
734 /* Check if file matches category */
735 if (DetermineCategory(path,c) == c) {
736 cout << "[" << catname << "] testing image " << i << " : OK" << endl;
737 c_succes[c]++;
738 } else {
[97]739 cout << "[" << catname << "] testing image " << i << " : FAIL" << endl;
740 DetermineCategory(path,c,opt_verbose);
741 }
[96]742 }
743 cout << "[" << catname << "] results " << c_succes[c] << "/" << c_total[c] << endl;
744 }
[98]745
[96]746 /* Display grand total */
747 cout << "=== Totals ===" << endl;
[97]748 cout << "Clasifier used: ";
749 if (opt_histogram)
750 cout << "histogram";
751 else if (opt_block)
752 cout << "block";
753 cout << endl;
754
[96]755 for (int c = 0; c < CATEGORY_SIZE; c++)
756 {
757 catname = categories[c];
758 printf ("[%-20s] %i/%i\n",catname,c_succes[c],c_total[c]);
759 all_total += c_total[c];
760 all_succes += c_succes[c];
761 }
[98]762 printf ("[%-20s] %i/%i\n","total",all_succes,all_total);
[96]763 cout << "Press any key to continue..."; cin.get();
764
765
766 return true;
767}
Note: See TracBrowser for help on using the repository browser.