/********************************************************************************************
 *	Image Feature Extractor: Recursive Extraction Algorithm
 *	
 *	Bobby Anguelov - banguelov@cs.up.ac.za (2007)
 *
 *	Description :	Feature Extraction Functions
 *	
 *	Notes :
 *  -----------------------------------------------------------------------------------------
 *	This simply extracts images out of a 8bit grayscale image where the background is black
 *	and the objects are white. Increasing the radius value will increase the radius of the
 *	object added to the neighbour list. This is how i achieve some basic reconstruction, its
 *	ideal but its better than nothing.
 *	Computationally it is rather expensive but in my research all extraction algorithm tend to 
 *	be expensive. In my testing on a AMD X2 5600+ this algorithm barely had any effect on 
 *	performance, on my work P4 3.0ghz, it significantly impacted performance.
 *	Basically run the featureExtractor function on a image stored in an unsigned char (8bit) 
 *	array, and provide the image width and height values.
 ********************************************************************************************/

/************************************************************************************
 *	code by : bobby anguelov - banguelov@cs.up.ac.za
 *	downloaded from : takinginitiative.wordpress.org
 *
 *	code is free for use in whatever way you want, however if you work for a game
 *	development firm you are obliged to offer me a job :P (haha i wish)
 ************************************************************************************/

//pixel helper struct
struct pixel
{
	int x, y;
};

//include radon trasformer
#include "radonTransformer.h"

class featureExtractor
{
public: 

	void extract( unsigned char* img, int w, int h )
	{		
		vector<pixel> object;
		int objectCount = 0;		

		//go through all the pixels
		for ( int y = 0; y < h; y++ )
		{
			for ( int x = 0; x < w; x++ )
			{
				if (img[y*w+x] == 255)
				{	
					//get object
					object = getNeighbours(img, x, y, w, h);
					
					//do all further processing here as the object is erased on next step

					objectCount++;
				}
			}
		}

		//display object count
		cout << "Objects Detected: " << objectCount << endl;
	}

private:

	vector<pixel> getNeighbours(unsigned char* img, int x, int y, int w, int h)
	{	
		vector<pixel> neighbours;
		pixel p = {0,0};

		//get list of neighbours
		//--------------------------		
		int radius = 10;
		int rowStart, rowEnd, colStart, colEnd;
				
		//set ranges
		if ( y - radius < 0 ) rowStart = 0;
		else rowStart = y - radius;

		if ( y + radius >= h ) rowEnd = h - 1;
		else rowEnd = y + radius;

		if ( x - radius < 0 ) colStart = 0;
		else colStart = x - radius;

		if ( x + radius >= w ) colEnd = w - 1;
		else colEnd = x + radius;

		for ( int r = rowStart; r <= rowEnd; r++ )
		{
			for ( int c = colStart; c <= colEnd; c++ )
			{	
				if ( img[ r * w + c ] == 255 ) 
				{
					p.x = c; p.y = r;
					neighbours.push_back( p );					
					img[ r * w + c ] = 100;
				}
			}
		}

		//return their neighbours
		if ( neighbours.size() != 0 )
		{
			int s = neighbours.size();			

			for ( int i = 0; i < s; i++ )
			{
				//get neighbours the neighbouring block
				vector<pixel> newNeighbours = getNeighbours(img, neighbours[i].x, neighbours[i].y, w, h);
				
				//push new neighbours onto object stack
				for ( int j = 0; j < newNeighbours.size(); j++ )
				{
					neighbours.push_back(newNeighbours[j]);
				}				
			}		

			return neighbours;
		}

		//if no neighbours return empty vector
		else
		{
			return neighbours;
		}
	}
};