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

Last change on this file since 219 was 100, checked in by Rick van der Zwet, 15 years ago

Special feature to be handed in.

File size: 23.1 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
[100]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"
[96]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
[100]51// Find common coloured block shapes as characteristics
[98]52// Walk over image with opt_spread steps, if pixel -within opt_tolerance- matches previous pixel
[100]53// make the size of the specific block bigger. Blocks can be horizontally and vertically attached
[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
[100]60// ===========Block Interesting Results ===========================
61// opt_spread | opt_tolerance | total | (almost correct)
62// ------------|---------------|-------|---------------------------
63// 10 | 10 | 20/41 | crowd, downhill, icehockey
64// 10 | 20 | 15/41 | crowd, downhill
65// 10 | 50 | 13/41 | crowd, downhill
66// 20 | 10 | 17/41 | crowd, icehockey, downhill
67// 20 | 20 | 17/41 | crowd, downhill, icehockey
68// 50 | 10 | 13/41 |
69// 50 | 20 | 14/41 | crowd, downhill
70// 50 | 50 | 12/41 | crowd, downhill
71// 100 | 100 | 10/41 | icehockey
[97]72
[100]73
74
75
[96]76// Some prototyping foo on functions
[97]77#define p_err(err_msg) printf("ERROR: %s\n", err_msg);
[96]78#define _return(err_msg, retval) printf("DEBUG: %s\n",err_msg); cin.get(); return(retval);
[97]79#define cout_status(msg,flag) cout << msg; (flag) ? cout << " off" : cout << " on"; cout << endl;
[98]80#define cout_point(x,y) "[" << x << "," << y << "]"
[96]81
[98]82// Default options
83bool opt_debug = false;
[97]84bool opt_verbose = false;
[98]85bool opt_histogram = false;
[97]86bool opt_block = true;
87
[96]88bool file_exists(const char * filename)
89{
90 if (FILE * file = fopen(filename, "r"))
91 {
92 fclose(file);
93 return true;
94 }
95 return false;
96}
97
98
99int main(int argc, char **argv)
100{
101 char dbdir[MAX_PATH];
102 char testdir[MAX_PATH];
103
104#if defined(TRAINING_DIR_DEBUG)
105 if (strcpy_s(dbdir, TRAINING_DIR_DEBUG) != 0) {
106 _return("Cannot copy TRAINING_DIR_DEBUG",1);
107 }
108 if (strcpy_s(testdir, TESTSET_DIR_DEBUG) != 0) {
109 _return("Cannot copy TESTSET_DIR_DEBUG",2);
110 }
111#else
112 // ask the user for the image database
113 // in the image directory, the images are stored in categorized
114 // folders. store the descriptors we calculate in the same
115 // folder as the image
116 if (XBrowseForFolder(NULL, "Please select image database folder", NULL, dbdir, sizeof(dbdir)) == FALSE)
117 return 0;
118 if (strlen(dbdir) == 0)
119 return 0;
[98]120 if (XBrowseForFolder(NULL, "Please select image testset batch folder, could be any folder", NULL, testdir, sizeof(testdir)) == FALSE)
[96]121 return 0;
122 if (strlen(testdir) == 0)
123 return 0;
124
125#endif
126
127#if DEBUG
128 if (!LoadAverages(dbdir)){
129 _return("Unable to load averages",1);
130 }
131
132 if (!DetermineWinterSportBatch(testdir)) {
133 _return("could not run winter sport batch",1);
134 }
135 return(0);
136#endif
137
138 // ask the user which option to use
139 while (true)
140 {
141 //system("cls");
142 cout << "Using database directory: " << dbdir << endl;
143 cout << "Using test directory: " << testdir << endl;
144 cout << "Using categories: " << endl;
145 for (int i = 0; i < CATEGORY_SIZE; i++)
146 {
147 cout << " - " << categories[i] << endl;
148 }
149 cout << "***************************" << endl;
150 cout << "* Winter Olympic Imagery *" << endl;
151 cout << "***************************" << endl;
152 cout << endl;
153 cout << "1. calculate descriptors" << endl;
[98]154 cout << "2. categorize descriptors (aka averages)" << endl;
155 cout << "3. determine winter sport on single image" << endl;
[96]156 cout << "4. batch test winter sport" << endl;
[98]157 cout << "9. Show averages" << endl;
158 cout << endl;
159 cout_status("d. Turn debug mode", opt_debug);
[97]160 cout_status("v. Turn verbose mode", opt_verbose);
161 cout_status("h. Turn histogram classifier", opt_histogram);
[98]162 cout_status("b. Turn block classifier", opt_block);
163 cout << endl;
164 cout << "==== Parameters Block Classifier ====" << endl;
165 cout << "s. Set spread [currently: " << opt_spread << "]" << endl;
166 cout << "t. Set Tolerance [currently: " << opt_tolerance << "]" << endl;
[97]167
[96]168 cout << "Please select option, or type 'q' to quit: ";
169 char c = _getch();
170 cout << c << endl;
171 fflush(stdin);
172 // start the chosen option
173 switch (c)
[97]174 {
[96]175 case 'q':
176 return 0;
177 case '1':
178 if (!CalculateDescriptors(dbdir)) {
179 _return("could not calculate descriptors",1);
180 }
181 break;
182 case '2':
183 if (!CategorizeDescriptors(dbdir)){
184 _return("could not categorize descriptors",1);
185 }
186 break;
187 case '3':
188 if (!LoadAverages(dbdir)){
189 _return("Unable to load averages",1);
190 }
191
192 if (!DetermineWinterSportSelect()){
193 _return("could not determine winter sport",1);
194 }
195 break;
196 case '4':
197 if (!LoadAverages(dbdir)){
198 _return("Unable to load averages",1);
199 }
200
201 if (!DetermineWinterSportBatch(testdir)) {
202 _return("could not run winter sport batch",1);
203 }
204 break;
[98]205 case '9':
206 if (!LoadAverages(dbdir)){
207 _return("Unable to load averages",1);
208 }
209 if (!ShowAverages(testdir)) {
210 _return("Unable to show averages",1);
211 }
212 break;
213 case 'd':
214 opt_debug = (!opt_debug);
215 break;
[96]216 case 'v':
[97]217 opt_verbose = (!opt_verbose);
218 break;
219 case 'b':
220 opt_block = (!opt_block);
221 break;
222 case 'h':
223 opt_histogram = (!opt_histogram);
224 break;
[98]225 case 's':
226 cout << "Spread value: ";
227 cin >> opt_spread;
228 cout << "WARNING: Make sure to re-classify before (Batch)Testing" << endl;
229 cout << "Any key to continue..." << endl; cin.get();
230 break;
231 case 't':
232 cout << "Tolerance value: ";
233 cin >> opt_tolerance;
234 cout << "WARNING: Make sure to re-classify before (Batch)Testing" << endl;
235 cout << "Any key to continue..." << endl; cin.get();
236 break;
237
[96]238 default:
239 continue;
240 }
241 }
242 return 0;
243}
244
245// histogram should be a preallocated array of size BIN_COUNT*BIN_COUNT*BIN_COUNT elements and will
246// be filled with the color histogram of the image where path points at
247bool CalculateDescriptor(const char *path, float *histogram)
248{
249 // load the image
250 CxImage image(path, CXIMAGE_FORMAT_JPG);
251 if (!image.IsValid())
252 return false;
253 // clear histogram
254 memset(histogram, 0, BIN_COUNT*BIN_COUNT*BIN_COUNT * sizeof(float));
255 // walk through the pixels to fill the histogram
256 int width = (int)image.GetWidth();
257 int height = (int)image.GetHeight();
258 int bin_r, bin_g, bin_b;
259 for (int y = 0; y < height; y++)
260 {
261 for (int x = 0; x < width; x++)
262 {
263 // Note: CxImage library starts counting at lower-left corner of the image,
264 // which is seen as the top of the image. however, usually images
265 // start counting from the top-left corner of the image. thus if you
266 // want to get pixel(2, 2) from the top-left you would have to ask
267 // for pixel (2, height - 2 - 1) from CxImage. although in this
268 // situation we don't care which pixel is where, we only care about
269 // its color.
270 RGBQUAD rgb = image.BlindGetPixelColor(x, y, false);
271 // determine the bin this color falls in
272 bin_r = rgb.rgbRed / (256 / BIN_COUNT);
273 bin_g = rgb.rgbGreen / (256 / BIN_COUNT);
274 bin_b = rgb.rgbBlue / (256 / BIN_COUNT);
275 histogram[bin_r*BIN_COUNT*BIN_COUNT + bin_g*BIN_COUNT + bin_b]++;
276 }
277 }
278 // normalize the histogram so that all together the values will add up
279 // to one. since there are width * height pixels, we divide each value
280 // by this amount
281 for (int i = 0; i < BIN_COUNT*BIN_COUNT*BIN_COUNT; i++)
282 histogram[i] /= width * height;
283 return true;
284}
285
[98]286struct point {
287 int x;
288 int y;
289};
290
291
[97]292// histogram should be a preallocated array of size BIN_COUNT*BIN_COUNT*BIN_COUNT elements and will
293// be filled with the color histogram of the image where path points at
294bool CalculateBlock(const char *path, float *block)
295{
296 // load the image
297 CxImage image(path, CXIMAGE_FORMAT_JPG);
298 if (!image.IsValid())
299 return false;
[98]300
[97]301 // clear histogram
[98]302 memset(block, 0, MAX_BLOCKSIZE * sizeof(float));
303
[97]304 // walk through the pixels to fill the histogram
305 const int width = (int)image.GetWidth();
306 const int height = (int)image.GetHeight();
307
[98]308 int * status = new int [width * height];
309 //memset(status,0, width * height * sizeof(int));
[97]310
[98]311 queue<point> queue;
312 int rgb_current, rgb_right, rgb_up = 0;
[97]313 int block_size = 0;
[98]314 point p, p_right, p_up;
[97]315
[98]316 RGBQUAD rgb;
317
318 // Pixel field status
319 // 0 = No need for processing
320 // 1 = Need processing
321 // 2 = Done processing
322 for (int x = 0; x < width; x += opt_spread)
323 for (int y = 0; y < height; y += opt_spread)
324 status[x * height + y] = 1;
325
326 for (int x = 0; x < width; x += opt_spread)
[97]327 {
[98]328 for (int y = 0; y < height; y += opt_spread)
[97]329 {
[98]330 // Only process if required to and not yet done
331 if (status[x * height + y] != 1) {
332 if (opt_debug)
333 cout << "Already processed point " << cout_point(x,y) << endl;
334 continue;
335 }
[97]336
[98]337 if(opt_debug)
338 cout << "Testing new point " << cout_point(x,y) << endl;
339
340 // Stack based expantion and evaluation
341 block_size = 0;
342 p.x = x;
343 p.y = y;
344 queue.push(p);
345
346 while (!queue.empty())
347 {
348 // Note: CxImage library starts counting at lower-left corner of the image
349 // which is seen as the top of the image.
350 p = queue.front();
351 queue.pop();
352
353 // Make sure not to process points twice
354 if (status[p.x * height + p.y] != 1)
355 continue;
356
357 if (opt_debug)
358 cout << "Processing point " << cout_point(p.x,p.y) << endl;
359
360 rgb = image.BlindGetPixelColor(p.x, p.y, false);
361 rgb_current = (rgb.rgbRed + rgb.rgbBlue + rgb.rgbGreen);
362
363 p_right.x = p.x + opt_spread;
364 p_right.y = p.y;
365
366 // Check if right one fits the bill
367 if (p_right.x < width)
368 {
369 rgb = image.BlindGetPixelColor(p_right.x, p_right.y, false);
370 rgb_right = (rgb.rgbRed + rgb.rgbBlue + rgb.rgbGreen);
371
372 if (abs(rgb_right - rgb_current) < opt_tolerance)
373 {
374 if (opt_debug)
375 cout << "Right point " << cout_point(p_right.x,p_right.y) << " gets included in block" << endl;
376
377 block_size++;
378 queue.push(p_right);
379 }
380 }
381
382 // Check if up one fits the bill
383 p_up.x = p.x;
384 p_up.y = p.y + opt_spread;
385 if (p_up.y < height)
386 {
387 rgb = image.BlindGetPixelColor(p_up.x, p_up.y, false);
388 rgb_up = (rgb.rgbRed + rgb.rgbBlue + rgb.rgbGreen);
389
390 if (abs(rgb_up - rgb_current) < opt_tolerance)
391 {
392 if (opt_debug)
393 cout << "Upper point " << cout_point(p_up.x, p_up.y) << " gets included in block" << endl;
394
395 block_size++;
396 queue.push(p_up);
397 }
398 }
399 status[p.x * height + p.y] = 2;
[97]400 }
[98]401 if (opt_debug)
402 cout << cout_point(x,y) << " blocksize " << block_size << endl;
403 if (block_size > MAX_BLOCKSIZE) {
404 cout << "WARN: block_size larger than fixed limit of " << MAX_BLOCKSIZE << endl;
405 block_size = MAX_BLOCKSIZE;
406 }
407
408 block[block_size]++;
[97]409 }
410 }
[98]411
412 delete status;
[97]413 return true;
414}
415
[96]416bool CalculateDescriptors(const char *basedir)
417{
418 // the histogram that we reuse for each image
419 float *histogram = new float[BIN_COUNT*BIN_COUNT*BIN_COUNT];
[98]420 float *block = new float[MAX_BLOCKSIZE];
[96]421 // walk through all images
422 // Note: each of the three categories has 50 images
423 char path[MAX_PATH];
424 char catdir[MAX_PATH];
425 const char *catname;
426 FILE *file = NULL;
427 for (int c = 0; c < CATEGORY_SIZE; c++)
428 {
429 catname = categories[c];
430 sprintf(catdir, "%s\\%s\\", basedir, catname);
431 cout << "[" << catname << "] Using directory " << catdir << endl;
432
433 // process the images in the directory
434 for (int i = 1; i <= 50; i++)
435 {
436 SAFE_SPRINTF(path, sizeof(path), "%s%i.jpg", catdir, i);
437 if (!file_exists(path)) {
438 continue;
439 }
440 cout << "[" << catname << "] processing image " << i << endl;
441 // calculate the histogram descriptor
442 if (!CalculateDescriptor(path, histogram))
443 goto failure;
[97]444
445 if (!CalculateBlock(path, block))
446 goto failure;
447
[100]448 if (opt_verbose) {
449 for (int u = 0; u < MAX_BLOCKSIZE; u++) {
450 if (block[u])
451 cout << "Blocksize " << u << " : " << block[u] << endl;
452 }
453 }
454
455
[97]456 // save the descriptor,block to disk
[96]457 SAFE_SPRINTF(path, sizeof(path), "%s%i.dat", catdir, i);
458 if ((file = fopen(path, "wb")) == NULL)
459 goto failure;
460 if (fwrite(histogram, sizeof(float), BIN_COUNT*BIN_COUNT*BIN_COUNT, file) != BIN_COUNT*BIN_COUNT*BIN_COUNT)
461 goto failure;
[98]462 if (fwrite(block, sizeof(float), MAX_BLOCKSIZE, file) != MAX_BLOCKSIZE)
[97]463 goto failure;
[96]464 SAFE_CLOSEFILE(file);
[97]465
466
[96]467 }
468 }
469 // release resources
470 SAFE_DELETE_ARRAY(histogram);
[97]471 SAFE_DELETE_ARRAY(block);
[96]472 return true;
473
474failure:
475 SAFE_CLOSEFILE(file);
476 SAFE_DELETE_ARRAY(histogram);
[97]477 SAFE_DELETE_ARRAY(block);
[96]478 return false;
479}
480
481bool CategorizeDescriptors(const char *basedir)
482{
483 // analyze the descriptors per category to determine the
484 // characteristics of that category
485 float *histogram = new float[BIN_COUNT*BIN_COUNT*BIN_COUNT];
[98]486 float *block = new float[MAX_BLOCKSIZE];
487 float *average_block = new float[MAX_BLOCKSIZE];
[96]488 float *average = new float[BIN_COUNT*BIN_COUNT*BIN_COUNT];
489 // walk through all descriptors
490 char path[MAX_PATH];
491 char catdir[MAX_PATH];
492 const char *catname;
493 FILE *file = NULL;
494 int c_size = 0;
495 for (int c = 0; c < CATEGORY_SIZE; c++)
496 {
497 c_size = 0;
498 catname = categories[c];
499 sprintf(catdir,"%s\\%s\\", basedir, catname);
500
[100]501 // Make sure initial values are 0
502 memset(average, 0, BIN_COUNT*BIN_COUNT*BIN_COUNT * sizeof(float));
503 memset(average_block, 0, MAX_BLOCKSIZE * sizeof(float));
504
[96]505 // average all descriptors
506 for (int i = 1; i <= 50; i++)
507 {
508 SAFE_SPRINTF(path, sizeof(path), "%s%i.dat", catdir, i);
509 if (!file_exists(path)) {
[97]510 p_err("File does not exists");
[96]511 continue;
512 }
513 cout << "[" << catname << "] processing image " << i << endl;
514 // load the histogram descriptor
[97]515 if ((file = fopen(path, "rb")) == NULL) {
516 p_err("Cannot open average datafile");
[96]517 goto failure;
[97]518 }
519 if (fread(histogram, sizeof(float), BIN_COUNT*BIN_COUNT*BIN_COUNT, file) != BIN_COUNT*BIN_COUNT*BIN_COUNT) {
520 p_err("Cannot read histogram");
[96]521 goto failure;
[97]522 }
[98]523 if (fread(block, sizeof(float), MAX_BLOCKSIZE, file) != MAX_BLOCKSIZE) {
[97]524 p_err("Cannot read block");
525 goto failure;
526 }
527
[96]528 SAFE_CLOSEFILE(file);
529 // add the value of each bin to the average
530 for (int b = 0; b < BIN_COUNT*BIN_COUNT*BIN_COUNT; b++)
531 average[b] += histogram[b];
532
[98]533 for (int b = 0; b < MAX_BLOCKSIZE; b++)
[97]534 average_block[b] += block[b];
535
[96]536 c_size++;
537 }
538
539 for (int b = 0; b < BIN_COUNT*BIN_COUNT*BIN_COUNT; b++)
540 average[b] /= c_size;
[98]541
[100]542 for (int b = 0; b < MAX_BLOCKSIZE; b++) {
[97]543 average_block[b] /= c_size;
[100]544 }
[97]545
[96]546 // save the average to disk
547 SAFE_SPRINTF(path, sizeof(path), "%s%s.dat", catdir, "average");
548 if ((file = fopen(path, "wb")) == NULL)
549 goto failure;
550 if (fwrite(average, sizeof(float), BIN_COUNT*BIN_COUNT*BIN_COUNT, file) != BIN_COUNT*BIN_COUNT*BIN_COUNT)
551 goto failure;
[98]552 if (fwrite(average_block, sizeof(float), MAX_BLOCKSIZE, file) != MAX_BLOCKSIZE)
[97]553 goto failure;
554
[96]555 SAFE_CLOSEFILE(file);
556 }
557 // release resources
558 SAFE_DELETE_ARRAY(histogram);
559 SAFE_DELETE_ARRAY(average);
[97]560 SAFE_DELETE_ARRAY(block);
[96]561 return true;
562
563failure:
564 SAFE_CLOSEFILE(file);
565 SAFE_DELETE_ARRAY(histogram);
[97]566 SAFE_DELETE_ARRAY(block);
[96]567 return false;
568}
569
570bool LoadAverages(const char *basedir) {
571 /* determine the distance to each category */
572 const char *catname;
573 char catdir[MAX_PATH];
574 char path[MAX_PATH];
575 FILE *file = NULL;
576
577 for (int c = 0; c < CATEGORY_SIZE; c++)
578 {
579 catname = categories[c];
580 sprintf(catdir, "%s\\%s\\", basedir, catname);
581
582 // load the average from disk
583 SAFE_SPRINTF(path, sizeof(path), "%s%s.dat", catdir, "average");
584 if ((file = fopen(path, "rb")) == NULL) {
585 cout << "Cannot open " << path << endl;
586 return false;
587 }
588 if (fread(average[c], sizeof(float), BIN_COUNT*BIN_COUNT*BIN_COUNT, file) != BIN_COUNT*BIN_COUNT*BIN_COUNT)
589 return false;
[98]590 if (fread(average_block[c], sizeof(float), MAX_BLOCKSIZE, file) != MAX_BLOCKSIZE)
[97]591 return false;
592
[96]593 SAFE_CLOSEFILE(file);
594 }
595 return true;
596}
597
[98]598
599bool ShowAverages(const char *basedir) {
600
601 if (opt_histogram) {
602 cout << "Histogram averages" << endl;
603 for (int c = 0; c < CATEGORY_SIZE; c++) {
604 cout << "Category [" << categories[c] << "] " << endl;
605 for (int i = 1; i <= BIN_COUNT*BIN_COUNT*BIN_COUNT; i++) {
606 cout << fixed << setprecision(2) << average[c][i-1] << " ";
607 if ((i % 10) == 0) cout << endl;
608 }
609 cout << endl;
610 }
611 }
612 if (opt_block) {
613 cout << "Block averages" << endl;
614 for (int c = 0; c < CATEGORY_SIZE; c++) {
615 cout << "Category [" << categories[c] << "] " << endl;
616 for (int i = 1; i < MAX_BLOCKSIZE; i++) {
617 cout << fixed << setprecision(2) << average_block[c][i-1] << " ";
618 if ((i % 10) == 0) cout << endl;
619 }
620 cout << endl;
621
622 }
623 }
624 return true;
625}
[97]626int DetermineCategory(const char *path, const int guess=-1, const bool verbose=false) {
[96]627 float *histogram = new float[BIN_COUNT*BIN_COUNT*BIN_COUNT];
[98]628 float *block = new float[MAX_BLOCKSIZE];
[96]629 float cat2dist[CATEGORY_SIZE];
[97]630 float cat2block[CATEGORY_SIZE];
[96]631
632 /* First category default best canidate */
[97]633 int cat_histogram = 0;
634 int cat_block = 0;
[96]635
636 /* calculate the histogram of the image */
637 if (!CalculateDescriptor(path, histogram))
638 return -1;
639
[97]640 if (!CalculateBlock(path, block))
641 return -1;
642
[96]643 /* determine the distance to each category */
644 for (int c = 0; c < CATEGORY_SIZE; c++)
645 {
646 // determine distance
647 cat2dist[c] = 0.0f;
[97]648 cat2block[c] = 0.0f;
[96]649 for (int b = 0; b < BIN_COUNT*BIN_COUNT*BIN_COUNT; b++)
650 cat2dist[c] += fabs(histogram[b] - average[c][b]);
[97]651
[98]652 /* No including of the non-matching points currently */
653 for (int b = 1; b < MAX_BLOCKSIZE; b++)
[97]654 cat2block[c] += fabs(block[b] - average_block[c][b]);
[96]655 }
656
657 /* determine the winning category */
[97]658 for (int i = 1; i < CATEGORY_SIZE; i++) {
659 if (cat2dist[i] < cat2dist[cat_histogram])
660 cat_histogram = i;
661 if (cat2block[i] < cat2block[cat_block])
662 cat_block = i;
663 }
[96]664
665 if (verbose) {
666 /* Dirty hack to show some more details in case of failure */
[97]667 if (opt_histogram && guess != -1 && guess != cat_histogram) {
[96]668 for (int i = 0; i < CATEGORY_SIZE; i++) {
[97]669 printf("%s [histogram] distance to %-20s: %f %s\n", (cat_histogram == i) ? "*" : " ",
670 categories[i], cat2dist[i],(cat_histogram == i) ? "*" : "");
[96]671 }
672 }
[97]673 if (opt_block && guess != -1 && guess != cat_block) {
674 for (int i = 0; i < CATEGORY_SIZE; i++) {
675 printf("%s [block] distance to %-20s: %f %s\n", (cat_block == i) ? "*" : " ",
676 categories[i], cat2block[i],(cat_block == i) ? "*" : "");
677 }
678 }
679
[96]680 }
681
682 /* return result */
[97]683 if (opt_histogram) {
684 return cat_histogram;
685 }
686 else if (opt_block) {
687 return cat_block;
688 } else {
[98]689 return -1;
[97]690 }
[96]691}
692
693/* ask for an input image and determine the most likely
694* category it belongs to
695*/
696bool DetermineWinterSportSelect()
697{
698 float *histogram = new float[BIN_COUNT*BIN_COUNT*BIN_COUNT];
699 char path[MAX_PATH] = {0};
700 char catdir[MAX_PATH] = {0};
701 const char *catname = NULL;
702 FILE *file = NULL;
703 int c = NULL;
704 float cat2dist[CATEGORY_SIZE] = {0};
705
706 OPENFILENAME ofn = {0};
707 //ofn.lpstrFilter = "Image files\0*.jpg;*.png;*.bmp\0\0";
708 ofn.lpstrFilter = "Image files\0*.jpg\0\0";
709 ofn.lpstrFile = path;
710 ofn.nMaxFile = MAX_PATH;
711 ofn.lpstrTitle = "Choose image file";
712 ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
713 ofn.lStructSize = sizeof(OPENFILENAME);
714
715 if (GetOpenFileName(&ofn) == FALSE)
716 goto failure;
717
718 if ((c = DetermineCategory(path,-2)) == -1)
719 return false;
720
721 cout << "The category this image belongs is category: " << categories[c] << " [" << c << "]" << endl;
722 cout << "Press any key to continue... ";
723 _getch();
724 fflush(stdin);
725 // release resources
726 SAFE_DELETE_ARRAY(histogram);
727 return true;
728
729failure:
730 SAFE_CLOSEFILE(file);
731 SAFE_DELETE_ARRAY(histogram);
732 return false;
733}
734
735bool DetermineWinterSportBatch(const char *basedir)
736{
737 const char *catname;
738 char catdir[MAX_PATH];
739 char path[MAX_PATH];
740
741 int all_total = 0;
742 int all_succes = 0;
743 int c_total[CATEGORY_SIZE] = {0};
744 int c_succes[CATEGORY_SIZE] = {0};
745
746 /* determine the distance to each category */
747 for (int c = 0; c < CATEGORY_SIZE; c++)
748 {
749 catname = categories[c];
750 sprintf(catdir, "%s\\%s\\", basedir, catname);
[98]751
[96]752 /* process the images in the directory */
753 for (int i = 1; i <= 50; i++)
754 {
755 SAFE_SPRINTF(path, sizeof(path), "%s%i.jpg", catdir, i);
756 if (!file_exists(path)) {
757 continue;
758 }
759
760 c_total[c]++;
761 /* Check if file matches category */
762 if (DetermineCategory(path,c) == c) {
763 cout << "[" << catname << "] testing image " << i << " : OK" << endl;
764 c_succes[c]++;
765 } else {
[97]766 cout << "[" << catname << "] testing image " << i << " : FAIL" << endl;
767 DetermineCategory(path,c,opt_verbose);
768 }
[96]769 }
770 cout << "[" << catname << "] results " << c_succes[c] << "/" << c_total[c] << endl;
771 }
[98]772
[96]773 /* Display grand total */
774 cout << "=== Totals ===" << endl;
[97]775 cout << "Clasifier used: ";
776 if (opt_histogram)
777 cout << "histogram";
778 else if (opt_block)
779 cout << "block";
780 cout << endl;
781
[96]782 for (int c = 0; c < CATEGORY_SIZE; c++)
783 {
784 catname = categories[c];
785 printf ("[%-20s] %i/%i\n",catname,c_succes[c],c_total[c]);
786 all_total += c_total[c];
787 all_succes += c_succes[c];
788 }
[98]789 printf ("[%-20s] %i/%i\n","total",all_succes,all_total);
[96]790 cout << "Press any key to continue..."; cin.get();
791
792
793 return true;
794}
Note: See TracBrowser for help on using the repository browser.