Index: liacs/MIR2010/SourceCode/hvdzwet.vcproj
===================================================================
--- liacs/MIR2010/SourceCode/hvdzwet.vcproj	(revision 96)
+++ liacs/MIR2010/SourceCode/hvdzwet.vcproj	(revision 97)
@@ -256,4 +256,8 @@
 			</File>
 			<File
+				RelativePath=".\reference_implementation.h"
+				>
+			</File>
+			<File
 				RelativePath="XBrowseForFolder.h"
 				>
Index: liacs/MIR2010/SourceCode/main.cpp
===================================================================
--- liacs/MIR2010/SourceCode/main.cpp	(revision 96)
+++ liacs/MIR2010/SourceCode/main.cpp	(revision 97)
@@ -40,8 +40,23 @@
 float average[CATEGORY_SIZE][BIN_COUNT*BIN_COUNT*BIN_COUNT];
 
+
+// Find common coloured shapes as characteristics
+// Walk over image with SPREAD steps, if pixel -within TOLERANCE- matches previous pixel 
+// make the size of the specific block bigger.
+#define TOLERANCE 20
+#define SPREAD 20
+#define MAX_SIZE 500
+float average_block[CATEGORY_SIZE][MAX_SIZE/SPREAD];
+
+
 // Some prototyping foo on functions
+#define p_err(err_msg) printf("ERROR: %s\n", err_msg);
 #define _return(err_msg, retval) printf("DEBUG: %s\n",err_msg); cin.get(); return(retval);
-
-bool verbose = false;
+#define cout_status(msg,flag) cout << msg; (flag) ? cout << " off" : cout << " on"; cout << endl;
+
+
+bool opt_verbose = false;
+bool opt_histogram = true;
+bool opt_block = true;
 
 bool file_exists(const char * filename)
@@ -114,9 +129,8 @@
 		cout << "3. determine winter sport" << endl;
 		cout << "4. batch test winter sport" << endl;
-		cout << "v. Turn verbose mode ";
-		if (verbose)
-			cout << "off" << endl;
-		else
-			cout << "on" << endl;
+		cout_status("v. Turn verbose mode", opt_verbose);
+		cout_status("h. Turn histogram classifier", opt_histogram);
+		cout_status("b. Turn block classifier", opt_block);
+
 		cout << endl;
 		cout << "Please select option, or type 'q' to quit: ";
@@ -126,5 +140,5 @@
 		// start the chosen option
 		switch (c)
-		{
+		{ 
 		case 'q':
 			return 0;
@@ -158,5 +172,12 @@
 			break;
 		case 'v':
-			verbose = (!verbose);
+			opt_verbose = (!opt_verbose);
+			break;
+		case 'b':
+			opt_block = (!opt_block);
+			break;
+		case 'h':
+			opt_histogram = (!opt_histogram);
+			break;
 		default:
 			continue;
@@ -207,8 +228,47 @@
 }
 
+// histogram should be a preallocated array of size BIN_COUNT*BIN_COUNT*BIN_COUNT elements and will
+// be filled with the color histogram of the image where path points at
+bool CalculateBlock(const char *path, float *block)
+{
+	// load the image
+	CxImage image(path, CXIMAGE_FORMAT_JPG);
+	if (!image.IsValid())
+		return false;
+	// clear histogram
+	memset(block, 0, MAX_SIZE/SPREAD * sizeof(float));
+	// walk through the pixels to fill the histogram
+	const int width = (int)image.GetWidth();
+	const int height = (int)image.GetHeight();
+
+	int rgb_value = 0;
+	int rgb_prev = 0;
+
+	int block_size = 0;
+
+	for (int y = 0; y < height; y += SPREAD)
+	{
+		for (int x = 0; x < width; x += SPREAD)
+		{
+			// Note: CxImage library starts counting at lower-left corner of the image,
+			//       which is seen as the top of the image.
+			RGBQUAD rgb = image.BlindGetPixelColor(x, y, false);
+			rgb_value = (rgb.rgbRed + rgb.rgbBlue + rgb.rgbGreen);
+
+			if (abs(rgb_value - rgb_prev) > TOLERANCE) {
+				block[block_size]++;
+				block_size = 1;
+			}
+			rgb_prev = rgb_value;
+		}
+	}
+	return true;
+}
+
 bool CalculateDescriptors(const char *basedir)
 {
 	// the histogram that we reuse for each image
 	float *histogram = new float[BIN_COUNT*BIN_COUNT*BIN_COUNT];
+	float *block = new float[MAX_SIZE/SPREAD];
 	// walk through all images
 	// Note: each of the three categories has 50 images
@@ -234,5 +294,9 @@
 			if (!CalculateDescriptor(path, histogram))
 				goto failure;
-			// save the descriptor to disk
+
+			if (!CalculateBlock(path, block))
+				goto failure;
+
+			// save the descriptor,block to disk
 			SAFE_SPRINTF(path, sizeof(path), "%s%i.dat", catdir, i);
 			if ((file = fopen(path, "wb")) == NULL)
@@ -240,9 +304,14 @@
 			if (fwrite(histogram, sizeof(float), BIN_COUNT*BIN_COUNT*BIN_COUNT, file) != BIN_COUNT*BIN_COUNT*BIN_COUNT)
 				goto failure;
+			if (fwrite(block, sizeof(float), MAX_SIZE/SPREAD, file) != MAX_SIZE/SPREAD)
+				goto failure;
 			SAFE_CLOSEFILE(file);
+
+
 		}
 	}
 	// release resources
 	SAFE_DELETE_ARRAY(histogram);
+	SAFE_DELETE_ARRAY(block);
 	return true;
 
@@ -250,4 +319,5 @@
 	SAFE_CLOSEFILE(file);
 	SAFE_DELETE_ARRAY(histogram);
+	SAFE_DELETE_ARRAY(block);
 	return false;
 }
@@ -258,4 +328,6 @@
 	// characteristics of that category
 	float *histogram = new float[BIN_COUNT*BIN_COUNT*BIN_COUNT];
+	float *block = new float[MAX_SIZE/SPREAD];
+	float *average_block = new float[MAX_SIZE/SPREAD];
 	float *average = new float[BIN_COUNT*BIN_COUNT*BIN_COUNT];
 	// walk through all descriptors
@@ -277,12 +349,22 @@
 			SAFE_SPRINTF(path, sizeof(path), "%s%i.dat", catdir, i);
 			if (!file_exists(path)) {
+				p_err("File does not exists");
 				continue;
 			}
 			cout << "[" << catname << "] processing image " << i << endl;
 			// load the histogram descriptor
-			if ((file = fopen(path, "rb")) == NULL)
-				goto failure;
-			if (fread(histogram, sizeof(float), BIN_COUNT*BIN_COUNT*BIN_COUNT, file) != BIN_COUNT*BIN_COUNT*BIN_COUNT)
-				goto failure;
+			if ((file = fopen(path, "rb")) == NULL) {
+				p_err("Cannot open average datafile");
+				goto failure;
+			}
+			if (fread(histogram, sizeof(float), BIN_COUNT*BIN_COUNT*BIN_COUNT, file) != BIN_COUNT*BIN_COUNT*BIN_COUNT) {
+				p_err("Cannot read histogram");
+				goto failure;
+			}
+			if (fread(block, sizeof(float), MAX_SIZE/SPREAD, file) != MAX_SIZE/SPREAD) {
+				p_err("Cannot read block");
+				goto failure;
+			}
+
 			SAFE_CLOSEFILE(file);
 			// add the value of each bin to the average
@@ -290,4 +372,7 @@
 				average[b] += histogram[b];
 
+			for (int b = 0; b < MAX_SIZE/SPREAD; b++)
+				average_block[b] += block[b];
+
 			c_size++;
 		}
@@ -295,4 +380,8 @@
 		for (int b = 0; b < BIN_COUNT*BIN_COUNT*BIN_COUNT; b++)
 			average[b] /= c_size;
+		
+		for (int b = 0; b < MAX_SIZE/SPREAD; b++)
+			average_block[b] /= c_size;
+
 		// save the average to disk
 		SAFE_SPRINTF(path, sizeof(path), "%s%s.dat", catdir, "average");
@@ -301,4 +390,7 @@
 		if (fwrite(average, sizeof(float), BIN_COUNT*BIN_COUNT*BIN_COUNT, file) != BIN_COUNT*BIN_COUNT*BIN_COUNT)
 			goto failure;
+		if (fwrite(average_block, sizeof(float), MAX_SIZE/SPREAD, file) != MAX_SIZE/SPREAD)
+			goto failure;
+
 		SAFE_CLOSEFILE(file);
 	}
@@ -306,4 +398,5 @@
 	SAFE_DELETE_ARRAY(histogram);
 	SAFE_DELETE_ARRAY(average);
+	SAFE_DELETE_ARRAY(block);
 	return true;
 
@@ -311,5 +404,5 @@
 	SAFE_CLOSEFILE(file);
 	SAFE_DELETE_ARRAY(histogram);
-	SAFE_DELETE_ARRAY(average);
+	SAFE_DELETE_ARRAY(block);
 	return false;
 }
@@ -335,4 +428,7 @@
 		if (fread(average[c], sizeof(float), BIN_COUNT*BIN_COUNT*BIN_COUNT, file) != BIN_COUNT*BIN_COUNT*BIN_COUNT)
 			return false;
+		if (fread(average_block[c], sizeof(float), MAX_SIZE/SPREAD, file) != MAX_SIZE/SPREAD)
+			return false;
+
 		SAFE_CLOSEFILE(file);
 	}
@@ -340,10 +436,13 @@
 }
 
-int DetermineCategory(const char *path, const int guess=-1) {
+int DetermineCategory(const char *path, const int guess=-1, const bool verbose=false) {
 	float *histogram = new float[BIN_COUNT*BIN_COUNT*BIN_COUNT];
+	float *block = new float[MAX_SIZE/SPREAD];
 	float cat2dist[CATEGORY_SIZE];
+	float cat2block[CATEGORY_SIZE];
 
 	/* First category default best canidate */
-	int retval = 0;
+	int cat_histogram = 0;
+	int cat_block = 0;
 
 	/* calculate the histogram of the image */
@@ -351,4 +450,7 @@
 		return -1;
 
+	if (!CalculateBlock(path, block))
+		return -1;
+
 	/* determine the distance to each category */
 	for (int c = 0; c < CATEGORY_SIZE; c++)
@@ -356,25 +458,46 @@
 		// determine distance
 		cat2dist[c] = 0.0f;
+		cat2block[c] = 0.0f;
 		for (int b = 0; b < BIN_COUNT*BIN_COUNT*BIN_COUNT; b++)
 			cat2dist[c] += fabs(histogram[b] - average[c][b]);
+
+		for (int b = 0; b < MAX_SIZE/SPREAD; b++)
+			cat2block[c] += fabs(block[b] - average_block[c][b]);
 	}
 
 	/* determine the winning category */
-	for (int i = 1; i < CATEGORY_SIZE; i++)
-		if (cat2dist[i] < cat2dist[retval])
-			retval = i;
+	for (int i = 1; i < CATEGORY_SIZE; i++) {
+		if (cat2dist[i] < cat2dist[cat_histogram])
+			cat_histogram = i;
+		if (cat2block[i] < cat2block[cat_block])
+			cat_block = i;
+	}
 
 	if (verbose) {
 		/* Dirty hack to show some more details in case of failure */
-		if (guess != -1 && guess != retval) {
+		if (opt_histogram && guess != -1 && guess != cat_histogram) {
 			for (int i = 0; i < CATEGORY_SIZE; i++) {		
-				printf("%s Distance to %-20s: %f %s\n", (retval == i) ? "*" : " ", 
-					categories[i], cat2dist[i],(retval == i) ? "*" : "");
-			}
-		}
+				printf("%s [histogram] distance to %-20s: %f %s\n", (cat_histogram == i) ? "*" : " ", 
+					categories[i], cat2dist[i],(cat_histogram == i) ? "*" : "");
+			}
+		}
+		if (opt_block && guess != -1 && guess != cat_block) {
+			for (int i = 0; i < CATEGORY_SIZE; i++) {		
+				printf("%s [block] distance to %-20s: %f %s\n", (cat_block == i) ? "*" : " ", 
+					categories[i], cat2block[i],(cat_block == i) ? "*" : "");
+			}
+		}
+
 	}
 
 	/* return result */
-	return retval;
+	if (opt_histogram) {
+		return cat_histogram;
+	}
+	else if (opt_block) {
+		return cat_block;
+	} else {
+	    return -1;
+	}
 }
 
@@ -452,5 +575,7 @@
 				c_succes[c]++;
 			} else {
-				cout << "[" << catname << "] testing image " << i << " : FAIL" << endl;			}
+				cout << "[" << catname << "] testing image " << i << " : FAIL" << endl;
+				DetermineCategory(path,c,opt_verbose);
+			}
 		}
 		cout << "[" << catname << "] results " << c_succes[c] << "/" << c_total[c] << endl;
@@ -459,4 +584,11 @@
 	/* Display grand total */
 	cout << "=== Totals ===" << endl;
+	cout << "Clasifier used: ";
+	if (opt_histogram)
+		cout << "histogram";
+	else if (opt_block)
+		cout << "block";
+	cout << endl;
+
 	for (int c = 0; c < CATEGORY_SIZE; c++)
 	{
