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
Line 
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>
8#include <iomanip>
9#include <queue>
10
11#include "cximage/ximage.h"
12#include "xbrowseforfolder.h"
13
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);
20bool ShowAverages(const char *basedir);
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
26// Names of categories (folders)
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
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
48float average[CATEGORY_SIZE][BIN_COUNT*BIN_COUNT*BIN_COUNT];
49
50
51// Find common coloured shapes as characteristics
52// Walk over image with opt_spread steps, if pixel -within opt_tolerance- matches previous pixel
53// make the size of the specific block bigger.
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];
59
60
61// Some prototyping foo on functions
62#define p_err(err_msg) printf("ERROR: %s\n", err_msg);
63#define _return(err_msg, retval) printf("DEBUG: %s\n",err_msg); cin.get(); return(retval);
64#define cout_status(msg,flag) cout << msg; (flag) ? cout << " off" : cout << " on"; cout << endl;
65#define cout_point(x,y) "[" << x << "," << y << "]"
66
67// Default options
68bool opt_debug = false;
69bool opt_verbose = false;
70bool opt_histogram = false;
71bool opt_block = true;
72
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;
105 if (XBrowseForFolder(NULL, "Please select image testset batch folder, could be any folder", NULL, testdir, sizeof(testdir)) == FALSE)
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;
139 cout << "2. categorize descriptors (aka averages)" << endl;
140 cout << "3. determine winter sport on single image" << endl;
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);
145 cout_status("v. Turn verbose mode", opt_verbose);
146 cout_status("h. Turn histogram classifier", opt_histogram);
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;
152
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)
159 {
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;
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;
201 case 'v':
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;
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
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
271struct point {
272 int x;
273 int y;
274};
275
276
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;
285
286 // clear histogram
287 memset(block, 0, MAX_BLOCKSIZE * sizeof(float));
288
289 // walk through the pixels to fill the histogram
290 const int width = (int)image.GetWidth();
291 const int height = (int)image.GetHeight();
292
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;
298 int block_size = 0;
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)
314 {
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;
398 return true;
399}
400
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];
405 float *block = new float[MAX_BLOCKSIZE];
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;
429
430 if (!CalculateBlock(path, block))
431 goto failure;
432
433 // save the descriptor,block to disk
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;
439 if (fwrite(block, sizeof(float), MAX_BLOCKSIZE, file) != MAX_BLOCKSIZE)
440 goto failure;
441 SAFE_CLOSEFILE(file);
442
443
444 }
445 }
446 // release resources
447 SAFE_DELETE_ARRAY(histogram);
448 SAFE_DELETE_ARRAY(block);
449 return true;
450
451failure:
452 SAFE_CLOSEFILE(file);
453 SAFE_DELETE_ARRAY(histogram);
454 SAFE_DELETE_ARRAY(block);
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];
463 float *block = new float[MAX_BLOCKSIZE];
464 float *average_block = new float[MAX_BLOCKSIZE];
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)) {
484 p_err("File does not exists");
485 continue;
486 }
487 cout << "[" << catname << "] processing image " << i << endl;
488 // load the histogram descriptor
489 if ((file = fopen(path, "rb")) == NULL) {
490 p_err("Cannot open average datafile");
491 goto failure;
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");
495 goto failure;
496 }
497 if (fread(block, sizeof(float), MAX_BLOCKSIZE, file) != MAX_BLOCKSIZE) {
498 p_err("Cannot read block");
499 goto failure;
500 }
501
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
507 for (int b = 0; b < MAX_BLOCKSIZE; b++)
508 average_block[b] += block[b];
509
510 c_size++;
511 }
512
513 for (int b = 0; b < BIN_COUNT*BIN_COUNT*BIN_COUNT; b++)
514 average[b] /= c_size;
515
516 for (int b = 0; b < MAX_BLOCKSIZE; b++)
517 average_block[b] /= c_size;
518
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;
525 if (fwrite(average_block, sizeof(float), MAX_BLOCKSIZE, file) != MAX_BLOCKSIZE)
526 goto failure;
527
528 SAFE_CLOSEFILE(file);
529 }
530 // release resources
531 SAFE_DELETE_ARRAY(histogram);
532 SAFE_DELETE_ARRAY(average);
533 SAFE_DELETE_ARRAY(block);
534 return true;
535
536failure:
537 SAFE_CLOSEFILE(file);
538 SAFE_DELETE_ARRAY(histogram);
539 SAFE_DELETE_ARRAY(block);
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;
563 if (fread(average_block[c], sizeof(float), MAX_BLOCKSIZE, file) != MAX_BLOCKSIZE)
564 return false;
565
566 SAFE_CLOSEFILE(file);
567 }
568 return true;
569}
570
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}
599int DetermineCategory(const char *path, const int guess=-1, const bool verbose=false) {
600 float *histogram = new float[BIN_COUNT*BIN_COUNT*BIN_COUNT];
601 float *block = new float[MAX_BLOCKSIZE];
602 float cat2dist[CATEGORY_SIZE];
603 float cat2block[CATEGORY_SIZE];
604
605 /* First category default best canidate */
606 int cat_histogram = 0;
607 int cat_block = 0;
608
609 /* calculate the histogram of the image */
610 if (!CalculateDescriptor(path, histogram))
611 return -1;
612
613 if (!CalculateBlock(path, block))
614 return -1;
615
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;
621 cat2block[c] = 0.0f;
622 for (int b = 0; b < BIN_COUNT*BIN_COUNT*BIN_COUNT; b++)
623 cat2dist[c] += fabs(histogram[b] - average[c][b]);
624
625 /* No including of the non-matching points currently */
626 for (int b = 1; b < MAX_BLOCKSIZE; b++)
627 cat2block[c] += fabs(block[b] - average_block[c][b]);
628 }
629
630 /* determine the winning category */
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 }
637
638 if (verbose) {
639 /* Dirty hack to show some more details in case of failure */
640 if (opt_histogram && guess != -1 && guess != cat_histogram) {
641 for (int i = 0; i < CATEGORY_SIZE; i++) {
642 printf("%s [histogram] distance to %-20s: %f %s\n", (cat_histogram == i) ? "*" : " ",
643 categories[i], cat2dist[i],(cat_histogram == i) ? "*" : "");
644 }
645 }
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
653 }
654
655 /* return result */
656 if (opt_histogram) {
657 return cat_histogram;
658 }
659 else if (opt_block) {
660 return cat_block;
661 } else {
662 return -1;
663 }
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);
724
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 {
739 cout << "[" << catname << "] testing image " << i << " : FAIL" << endl;
740 DetermineCategory(path,c,opt_verbose);
741 }
742 }
743 cout << "[" << catname << "] results " << c_succes[c] << "/" << c_total[c] << endl;
744 }
745
746 /* Display grand total */
747 cout << "=== Totals ===" << endl;
748 cout << "Clasifier used: ";
749 if (opt_histogram)
750 cout << "histogram";
751 else if (opt_block)
752 cout << "block";
753 cout << endl;
754
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 }
762 printf ("[%-20s] %i/%i\n","total",all_succes,all_total);
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.