// Main -- combines Sabreen's and Becky's code

/*
 * set your OS!
 *
 * in order to include the correct files...
 */

//#define WINDOWS_OS
#define MAC_OS

/*
 * include files for Mac OS X
 */
#ifdef MAC_OS

#include <OpenCV/OpenCV.h>
#include <stdio.h>
#include <ctype.h>
#include <math.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>       // for memset
#include <unistd.h>
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>
#include <BlobResult.h>

#include <fstream> 
#include <iostream>
using namespace std;

//#define ROOT_FOLDER "/Users/bfsnet/Desktop/SetWithOpenCV/"
//#define ROOT_FOLDER "/Users/dodds/Desktop/SetWithOpenCV/"
#define ROOT_FOLDER "/Users/admin/Desktop/SetWithOpenCV/"

#define MAXCOLORS 5

#endif



/* 
 * global data for passing among 
 *   the main loop (in main)
 *   the mouse-event handler (in mouseEventHandler)
 *   the server (in runServerThread)
 */
IplImage *inputImage=0;  // shared between mouse events and main loop
int swapVerticalValues = 0;  // shared between mouse events and main loop

int drawingRectangle=0;  // shared between mouse events and main loop
CvPoint origin;          // more rectangle/line-selection data
CvRect selection;

int runAlgorithm = 0;    // shared between server and main loop
int timeToQuitNow = 0;   // shared between server and main loop
int blobsAreOn = 1; // allows us to turn blob detection on and off
int removePixels = 0;




#include "mainHelperBG.h"
BlobData colorData[30];

#include "colorArrayBG.h"
#include "serverStuffSabreen6408.h"


ArrayColorDef currentColorArray;
ArrayColorDef totalColorArray[MAXCOLORS];



char* colorNames[MAXCOLORS];




/*
 * Mouse-event handling routine
 */
void mouseEventHandler( int event, int x, int y, int flags, void* param )
{
  int r,g,b;
  double h,s,v;
	
	if ( !inputImage )  return;  // no image, do nothing
  if (swapVerticalValues)  y = inputImage->height - y;   // platform-dependent!
  
  if ( event == CV_EVENT_MOUSEMOVE && drawingRectangle ) // are we pulling the corner of a rectangle?
  {
    // handle the geometry of the rectangle:
    selection.x = MIN(x,origin.x);  selection.y = MIN(y,origin.y);
    selection.width = MIN( selection.x + CV_IABS(x - origin.x), inputImage->width ) - MAX( selection.x, 0 );
    selection.height = MIN( selection.y + CV_IABS(y - origin.y), inputImage->height ) - MAX( selection.y, 0 );
  } // end of rectangle-drawing
    
  if ( event == CV_EVENT_RBUTTONDOWN && !(removePixels)) // did we right-click (or control-click?)
  {
    getrgb( inputImage, x, y, r, g, b );
	RGBtoHSV( r, g, b, h, s, v );
    printf("      right-click at (%d,%d): rgb=(%d,%d,%d)\n", x, y, r, g, b ) ;
	printf("		hsv=(%6.3f,%6.3f,%6.3f)\n",h,s,v);
    int N = 7;  // acceptable color width 
    currentColorArray.expandToFit( r, g, b, N ); // box of side 2N: upper corner
    //currentColor.expandToFit( r-N, g-N, b-N ); // and lower corner
    //currentColor.print();
  }
  
  if ( event == CV_EVENT_RBUTTONDOWN && removePixels)
  {
	getrgb( inputImage, x, y, r, g, b );
	RGBtoHSV( r, g, b, h, s, v );
    printf("      right-click at (%d,%d): rgb=(%d,%d,%d)\n", x, y, r, g, b ) ;
	printf("		hsv=(%6.3f,%6.3f,%6.3f)\n",h,s,v);
    int N = 7;  // acceptable color width 
    currentColorArray.subtractRange( r, g, b, N ); // box of side 2N: upper corner
    //currentColor.expandToFit( r-N, g-N, b-N ); // and lower corner
    //currentColor.print();
   }
		  
	if ( event == CV_EVENT_LBUTTONDOWN ) // did we left-click?
  {
    if (!drawingRectangle) // if we weren't drawing, now we start drawing a rectangle
    {
      origin = cvPoint(x,y);
      selection = cvRect(x,y,1,1);
      drawingRectangle = 1;
	  printf("begin drawing rectangle. \n");
    }
	
    else if(drawingRectangle && removePixels) // we'll remove the pixels in the enclosed rectangle
    {
      //currentColorArray.reset();
      for ( int col=selection.x ; col<=selection.x+selection.width ; ++col)
      {
        for ( int row=selection.y ; row<=selection.y+selection.height ; ++row) 
        {
		  int N = 10; // acceptable color width
          getrgb( inputImage, col, row, r, g, b );
          currentColorArray.subtractRange( r, g, b, N);
        }
      }
	  drawingRectangle = 0;
	  printf("end drawing subtraction rectangle. \n");
	  }
	  
	  
	else // drawing rectangle and adding pixels
	{
		 for ( int col=selection.x ; col<=selection.x+selection.width ; ++col)
      {
			for ( int row=selection.y ; row<=selection.y+selection.height ; ++row) 
        {
			int N = 10; // acceptable color width
			getrgb( inputImage, col, row, r, g, b );
			currentColorArray.expandToFit( r, g, b, N);
		}
      }
	  
      drawingRectangle = 0;
	  printf("end drawing addition rectangle. \n");
	  }
  }
	  
	  
	//printf("end of mouse event handler \n");
} // end of mouse event handler

void pixelsInArraybw(IplImage* INPUT, ArrayColorDef colorArray, IplImage* OUTPUT)
 {
	//printf(" beginning bw \n");
	int imageWidth  = INPUT-> width;
	int imageHeight = INPUT-> height;
	int r,g,b;
	for ( int col = 0; col < imageWidth; col++)
	{
		for ( int row = 0; row < imageHeight; row++)
		{
			getrgb(INPUT, col, row, r, g, b);
			if (colorArray.pixelMatch(r,g,b))
			{
				setbw(OUTPUT, col, row, 255);
				//printf("pixel set");
			}
			else
			{
				setbw(OUTPUT, col, row, 0);
			}
		}
	}
	
		 
}

void drawBorder(IplImage* IMAGE)
{

	int imageWidth  = IMAGE-> width;
	int imageHeight = IMAGE-> height;
	
	for( int col = 0; col < 3; col++)
	{
		for( int row = 0; row < imageHeight; row++)
		{
			setbw(IMAGE, col, row, 0);
		}
	}
	
	for( int col = imageWidth-3; col < imageWidth; col++)
	{
		for( int row = 0; row < imageHeight; row++)
		{
			setbw(IMAGE, col, row, 0);
		}
	}
	
	for( int col = 0; col < imageWidth; col++)
	{
		for( int row = 0; row < 3; row++)
		{
			setbw(IMAGE, col, row, 0);
		}
	}
	
	for( int col = 0; col < imageWidth; col++)
	{
		for( int row = imageHeight-3; row < imageHeight; row++)
		{
			setbw(IMAGE, col, row, 0);
		}
	}
}

/** 
  * totalColorArray handler -- allows us to load in an array with color definitions
  * for each color we look at.
  **/
  
  void tCAHandler()
  {
	char filename[255];
	colorNames[0] = "red";
	colorNames[1] = "yellow";
	colorNames[2] = "blue"; 
	colorNames[3] = "green";
	colorNames[4] = "pink";

	for( int i = 0; i < MAXCOLORS; i++)
	{
		currentColorArray.reset();
		sprintf(filename, "%s%sColorDef%d.txt", ROOT_FOLDER, colorNames[i], COLOR_STEP_SIZE);
		currentColorArray.loadFromFile( filename);
		totalColorArray[i].setAs(currentColorArray);
	}
   }

/*
 * MAIN
 */
int main( int argc, char** argv )
{	
  /*
   * set up vision server
   */
  int runServer = true;    

#ifdef MAC_OS               
  pthread_t serverThread;   // the identifier for the thread
  if (runServer)            // do we want to run the server?
  {
    printf("Creating serverThread.\n");
    int rc = pthread_create(&serverThread, NULL, runServerThread, NULL);
    if (rc) printf("ERROR in pthread_create: %d.\n", rc);
  }
#endif
  //printf("end setting up vision server\n");
  /*
   * set up image input source
   */
  enum { IMAGES_FROM_CAMERA, IMAGES_FROM_FOLDER, IMAGES_FROM_AVI_FILE };
  int captureType = IMAGES_FROM_CAMERA; 
  
  char* MOVIE_NAME = ROOT_FOLDER "path0.mpg"; 
  char* FOLDER_NAME = ROOT_FOLDER "tmp"; 
  //printf("FOLDER_NAME: %s", FOLDER_NAME);
  int MAX_FILE_NUMBER =34;  // the number of images in the folder
  int nextFileNumber = 0;    // the next file number to read 
  
  enum { LIVE, ONEFRAME, STILL };  // how are we now capturing
  int captureStatus = LIVE;
  
  CvCapture* capture = 0;  // the capture object to grab frames from a camera/avi file

  if ( captureType == IMAGES_FROM_CAMERA )   // initialize "capture," the image source
    capture = cvCaptureFromCAM( 0 );         // camera number zero, which is usually the one attached
  else if ( captureType == IMAGES_FROM_AVI_FILE )
    capture = cvCaptureFromAVI( MOVIE_NAME ); 
  else // captureType = IMAGES_FROM_FOLDER;
    capture = 0;
  //printf("end image input setup\n");
  
  /*
   * create windows for displaying images
   */
  //cvNamedWindow( "InputImage", CV_WINDOW_AUTOSIZE );
  //cvMoveWindow( "InputImage", 100, 100 );
  //cvSetMouseCallback( "InputImage", mouseEventHandler, 0 );  // Crazy, but it just might work
  cvNamedWindow( "OutputImage", CV_WINDOW_AUTOSIZE );
  cvMoveWindow( "OutputImage", 440, 100 );
  cvSetMouseCallback( "OutputImage", mouseEventHandler, 0);
  //cvNamedWindow( "BinaryImage", CV_WINDOW_AUTOSIZE );
  //cvMoveWindow( "BinaryImage", 220, 100 );
  
	//printf("created windows for displaying images\n");
  /*
   * create an initial image, displayImage, and any other images...
   */
  inputImage = cvCreateImage( cvSize(10,10), 8, 1 );
  IplImage* outputImage = NULL;
  IplImage* frame = NULL;  // image grabbed from camera
  IplImage* binaryImage = NULL;
  //printf("created inital images\n");
  
  /*
   * blob handling
   */
  CBlobResult blobs; 
  CBlob blobToShow;

  /*
   * Load in the tCA
   */
	if (blobsAreOn)
		tCAHandler();
  
  /*
   * MAIN LOOP
   */
  while (!timeToQuitNow)
  {//printf("beginning main loop\n");
    /*
     * INPUT IMAGE SETUP
     *
     * the goal here is to populate the _image_ variable with pixels
     *   depending on the source in captureType
     */
    if (captureStatus != STILL) 
    {
      if (captureType == IMAGES_FROM_FOLDER)
      {
        char filename[255];
        
        if (nextFileNumber > MAX_FILE_NUMBER || nextFileNumber < 0) nextFileNumber = 0;
        sprintf(filename,"%s/image%04d.bmp", FOLDER_NAME, nextFileNumber++);
        inputImage = cvLoadImage(filename, -1); // -1 means determine number of channels from format
      }
      else // captureType == IMAGES_FROM_AVI_FILE or IMAGES_FROM_CAMERA
      {
        frame = cvQueryFrame( capture );  
        if ( !frame  )
        {
          printf( "Frame not obtained when capturing!\n");
          printf( "Setting captureStatus to STILL.\n");
          captureStatus = STILL;
        }
        else  // set up the destination image, if needed
        {
          CvSize frameSize = cvGetSize(frame);
          if ( frameSize.width != inputImage->width || frameSize.height != inputImage->height )
          {
            cvReleaseImage( &inputImage );
            inputImage = cvCreateImage( frameSize, 8, 3 );
            inputImage->origin = frame->origin;
          } // image is OK and the right size, now
          cvCopy( frame, inputImage, 0 );  // copy the frame data into the image
        }
      }
      
      if (captureStatus == ONEFRAME)  captureStatus = STILL; // we got our one frame...
      // now, we keep that image until an event asks to grab a new one
	//printf("finished input image setup\n InputImage : %s", inputImage);
    }
    
    /*
     * OUTPUT IMAGE SETUP
     *
     * we need to make sure to set up the output images before processing!
     * (or other intermediate images)  we check to be sure they're the right size...
     */
    if ( outputImage == NULL || 
         ( inputImage->width != outputImage->width  || inputImage->height != outputImage->height ) ) 
    { 
      if (outputImage) cvReleaseImage( &outputImage );
      outputImage = cvCreateImage( cvGetSize(inputImage), 8, 3 );
    }
    cvCopy(inputImage, outputImage, NULL);  // copy input to output image as a starting point for outputImage
    
    if ( binaryImage == NULL ||
          ( inputImage->width != binaryImage->width || inputImage->height != binaryImage->height ) )
    {
      if (binaryImage) cvReleaseImage( &binaryImage );
      binaryImage = cvCreateImage( cvGetSize(inputImage), 8, 1);
    }
	
	pixelsInArraybw( inputImage, currentColorArray, binaryImage);
	//cvErode(binaryImage, binaryImage, NULL, 5);
				
	//printf("finished output image setup\n");
	
    /*
     * OUR ALGORITHM/PROCESSING/VISUALIZATION
     */
    if (runAlgorithm)
    {
      int b,r,g;
      // loop over the input image
      for ( int col=0 ; col<inputImage->width ; ++col) 
      {
        for ( int row=0 ; row<inputImage->height ; ++row) 
        {
          
          getrgb( inputImage, col, row, r, g, b );
          if ( currentColorArray.pixelMatch(r,g,b))
            {setrgb( outputImage, col, row, 255, 0, 0 );
			//setrgb( inputImage, col, row, 255, 255, 255);
			}
		  //if (col > 315 && col < 325)
		  //{
			//setrgb( outputImage, col, row, 147, 147, 147);
			//}
		  
		
          
        } // end row
      } //printf("end algorithm processing\n");// end col
    }
	
	
	//arrayified version... work please...
	if(blobsAreOn)
	{
	//CBlob allDestBlobs [30];
	CBlob destinationBlobs [3];


	for(int i=0; i < MAXCOLORS; ++i) { 
		pixelsInArraybw(inputImage, totalColorArray[i], binaryImage);
		drawBorder(binaryImage);

		blobs = CBlobResult( binaryImage, NULL, 100, true );

		blobs.Filter( blobs, B_INCLUDE, CBlobGetArea(), B_GREATER, 500);
		// Here, we could filter out the long rectangular blobs. We'd only go to it if we had single
		// color blobs, as there won't be many long ones if we have 2 or 3 color blobs.
		// This might end up in the main python file as well.
		// tCA = {red, yellow, blue, green, pink}
		int rr = (i==0 )? 255: (i==1)? 255: (i==2)? 0:   (i == 3)? 0:   255; //gets the proper color for the different cases
		int gg = (i==0)? 0:    (i==1)? 255: (i==2)? 0:   (i == 3)? 255:  20;
		int bb = (i==0)? 0:    (i==1)? 0:   (i==2)? 255: (i == 3)? 0:   147;
		
		CBlobGetArea getArea = CBlobGetArea(); 
		CBlobGetMinX getMinX = CBlobGetMinX();   
		CBlobGetMaxX getMaxX = CBlobGetMaxX();
		CBlobGetMinY getMinY = CBlobGetMinY();
		CBlobGetMaxY getMaxY = CBlobGetMaxY();
		//printf("-------------------------\n");
		for(int j=0; j<3;j++) {
			blobs.GetNthBlob( CBlobGetArea(), j+1, destinationBlobs[j] ); 
			//double area = getArea(destinationBlobs[j]);
			//printf("area = %f\n", area);
			
			int minxarea = (int) getMinX(destinationBlobs[j]);
			int maxxarea = (int) getMaxX(destinationBlobs[j]);
			int minyarea = (int) getMinY(destinationBlobs[j]);
			int maxyarea = (int) getMaxY(destinationBlobs[j]);
			colorData[i].xmin[j]=minxarea;
			colorData[i].xmax[j]=maxxarea;
			colorData[i].ymin[j]=minyarea;
			colorData[i].ymax[j]=maxyarea;
			colorData[i].colour= i;
			
			//printf("\nafter assignment\n");
			//printf("minx = %d\n", colorData[i].xmin[j]);
			//printf("maxx = %d\n", colorData[i].xmax[j]);
			//printf("miny = %d\n", colorData[i].ymin[j]);
			//printf("maxy = %d\n", colorData[i].ymax[j]);
			//printf("colour number is: %d\n\n", colorData[i].colour);  //1 is red, 2 is yellow, 3 is blue, 4 is green 
			destinationBlobs[j].FillBlob( outputImage, CV_RGB( rr, gg , bb ) );
		}
		//allDestBlobs[i] = destinationBlobs;
		//CBlobGetArea getArea = CBlobGetArea();
	}
	}

////////////////////////////////not arrayified version of junk above/////////////////////////////////////////////////////////
	
/*

	//color red blobs
	CBlob destinationBlob, destinationBlob2, destinationBlob3;
	currentColors[0].loadFromFile( ROOT_FOLDER"colorDef00.txt");
			

	// repaint the binary image, so we'll get just red blobs
	cvInRangeS( inputImage, cvScalar( currentColors[0].bmin, currentColors[0].gmin, currentColors[0].rmin), //min side of colors
				cvScalar( currentColors[0].bmax, currentColors[0].gmax, currentColors[0].rmax), //max side
				binaryImage );
				
	blobs = CBlobResult( binaryImage, NULL, 100, true );  

	blobs.Filter( blobs, B_INCLUDE, CBlobGetArea(), B_GREATER, 100 ); 

	blobs.GetNthBlob( CBlobGetArea(), 1, destinationBlob ); //find the area of the largest blob and save it to destinationBlob
	
	blobs.GetNthBlob( CBlobGetArea(), 2, destinationBlob2 ); //find the area of the second largest blob and save it to destinationBlob2
	
	blobs.GetNthBlob( CBlobGetArea(), 3, destinationBlob3 ); //find the area of the third largest blob and save it to destinationBlob3
	
	CBlobGetArea getArea = CBlobGetArea();  

	destinationBlob.FillBlob( outputImage, CV_RGB( 255, 0 , 0 ) ); //color largest 3 blobs red
	
	destinationBlob2.FillBlob( outputImage, CV_RGB( 255, 0, 0 ) ); 
	
	destinationBlob3.FillBlob( outputImage, CV_RGB( 255, 0, 0 ) );
	
	// color yellow blobs
	 
	currentColors[1].loadFromFile( ROOT_FOLDER"colorDef01.txt");

	// repaint the binary image, so we'll get different blobs
	cvInRangeS( inputImage, cvScalar( currentColors[1].bmin, currentColors[1].gmin, currentColors[1].rmin), //min side of colors
				cvScalar( currentColors[1].bmax, currentColors[1].gmax, currentColors[1].rmax), //max side
				binaryImage );
				
	blobs = CBlobResult( binaryImage, NULL, 100, true );  

	blobs.Filter( blobs, B_INCLUDE, CBlobGetArea(), B_GREATER, 100 ); 

	blobs.GetNthBlob( CBlobGetArea(), 1, destinationBlob ); //find the area of the largest blob and save it to destinationBlob
	
	blobs.GetNthBlob( CBlobGetArea(), 2, destinationBlob2 ); //find the area of the second largest blob and save it to destinationBlob2
	
	blobs.GetNthBlob( CBlobGetArea(), 3, destinationBlob3 ); //find the area of the third largest blob and save it to destinationBlob3
	
	destinationBlob.FillBlob( outputImage, CV_RGB( 255, 255 , 0 ) ); //color blobs yellow
	
	destinationBlob2.FillBlob( outputImage, CV_RGB( 255, 255, 0 ) ); 
	
	destinationBlob3.FillBlob( outputImage, CV_RGB( 255, 255, 0 ) ); 
	
	// color blue blobs blue
	
	currentColors[2].loadFromFile( ROOT_FOLDER"colorDef02.txt");
	
	// repaint the binary image, so we'll get different blobs
	cvInRangeS( inputImage, cvScalar( currentColors[2].bmin, currentColors[2].gmin, currentColors[2].rmin), //min side of colors
				cvScalar( currentColors[2].bmax, currentColors[2].gmax, currentColors[2].rmax), //max side
				binaryImage );

	blobs = CBlobResult( binaryImage, NULL, 100, true );  

	blobs.Filter( blobs, B_INCLUDE, CBlobGetArea(), B_GREATER, 100 ); 

	blobs.GetNthBlob( CBlobGetArea(), 1, destinationBlob ); //find the area of the largest blob and save it to destinationBlob
	
	blobs.GetNthBlob( CBlobGetArea(), 2, destinationBlob2 ); //find the area of the second largest blob and save it to destinationBlob2
	
	blobs.GetNthBlob( CBlobGetArea(), 3, destinationBlob3 ); //find the area of the third largest blob and save it to destinationBlob3

	destinationBlob.FillBlob( outputImage, CV_RGB( 0, 0 , 255 ) ); //color blobs blue
	
	destinationBlob2.FillBlob( outputImage, CV_RGB( 0, 0, 255 ) ); 
	
	destinationBlob3.FillBlob( outputImage, CV_RGB( 0, 0, 255 ) ); 
	
	// color green blobs green
	//CBlob destinationBlob, destinationBlob2, destinationBlob3;
	currentColors[3].loadFromFile( ROOT_FOLDER"colorDef03.txt");
	
	// repaint the binary image, so we'll get different blobs
	cvInRangeS( inputImage, cvScalar( currentColors[3].bmin, currentColors[3].gmin, currentColors[3].rmin), //min side of colors
				cvScalar( currentColors[3].bmax, currentColors[3].gmax, currentColors[3].rmax), //max side
				binaryImage );

	blobs = CBlobResult( binaryImage, NULL, 100, true );  

	blobs.Filter( blobs, B_INCLUDE, CBlobGetArea(), B_GREATER, 100 ); 

	blobs.GetNthBlob( CBlobGetArea(), 1, destinationBlob ); //find the area of the largest blob and save it to destinationBlob
	
	blobs.GetNthBlob( CBlobGetArea(), 2, destinationBlob2 ); //find the area of the second largest blob and save it to destinationBlob2
	
	blobs.GetNthBlob( CBlobGetArea(), 3, destinationBlob3 ); //find the area of the third largest blob and save it to destinationBlob3
	
	//CBlobGetArea getArea = CBlobGetArea();  
	
	//double area = getArea(destinationBlob); 

	destinationBlob.FillBlob( outputImage, CV_RGB( 0, 255 , 0 ) ); //color blobs green
	
	destinationBlob2.FillBlob( outputImage, CV_RGB( 0, 255, 0 ) ); 
	
	destinationBlob3.FillBlob( outputImage, CV_RGB( 0, 255, 0 ) ); 
	
*/
	
////////////////////////////////original code for junk above/////////////////////////////////////////////////////////////////	
	
	/**CBlobResult blobs; //original blob code -- no longer needed
	CBlob destinationBlob, destinationBlob2, destinationBlob3;

	blobs = CBlobResult( binaryImage, NULL, 100, true );  

	blobs.Filter( blobs, B_INCLUDE, CBlobGetArea(), B_GREATER, 100 ); 

	blobs.GetNthBlob( CBlobGetArea(), 1, destinationBlob ); //find the area of the largest blob and save it to destinationBlob
	
	blobs.GetNthBlob( CBlobGetArea(), 2, destinationBlob2 ); //find the area of the second largest blob and save it to destinationBlob2
	
	blobs.GetNthBlob( CBlobGetArea(), 3, destinationBlob3 ); //find the area of the third largest blob and save it to destinationBlob3
	
	CBlobGetArea getArea = CBlobGetArea();  
	
	//double area = getArea(destinationBlob); 

	destinationBlob.FillBlob( outputImage, CV_RGB( 255, 255, 0 ) ); //color largest blob yellow
	
	destinationBlob2.FillBlob( outputImage, CV_RGB( 255, 0, 0 ) ); //color 2nd largest blob red
	
	destinationBlob3.FillBlob( outputImage, CV_RGB( 0, 0, 255 ) ); //color 3rd largest blob blue
    **/
	
////////////////////////////////dealing with center matching/////////////////////////////////////////////////////////////////
//THIS NEEDS TO BE FIXED SO THAT IT ACTUALLY WORKS

/*
	double SAME_CENTER_THRESHHOLD = 100.0; // within 100 pixels => same center

    //bool foundSameCenter = false;
	//printf("Num of blobs: %03d",allDestBlobs.GetNumBlobs());
	printf("\n");
	CBlobGetHullArea getHullArea = CBlobGetHullArea();
	//double averageHullArea = 0.0;
	
	//gets all the x-centers of the blobs and store in an array
	double centers [30];
	for(int i=0; i < 30; ++i) {
		double blah = (allDestBlobs[i].MaxX()+allDestBlobs[i].MinX())/2;
		printf("max/min %d %d\n",allDestBlobs[i].MaxX(),allDestBlobs[i].MinX());
		centers[i] = blah;
	}
	for(int i =0; i < 30; i++) {
		printf("centers at %d is: -->%d\n",i,centers[i]);
	}
	
	for (i = 0 ; i< allDestBlobs.GetNumBlobs()-1; ++i) 
	{
		allDestBlobs.GetNthBlob( CBlobGetHullArea(), i, blobToShow);
		allDestBlobs.GetNthBlob( CBlobGetHullArea(), i+1, nextBlob);
		double thisCenter = blobToShow.sumx;
		double nextCenter = nextBlob.sumx;
		for (int k = 0; k<i; ++k)
		{
			if (fabs(thisCenter-shapeXCenters[k]) < SAME_CENTER_THRESHHOLD) 
				foundSameCenter = true;
		}
		if (foundSameCenter) break; //no more symbols
		//otherwise, this is a new symbol...
		if(true) blobToShow.FillBlob(outputImage, numSymbols==0? CV_RGB(255, 100, 0) :
										numSymbols == 1? CV_RGB(0, 255, 255) :
										CV_RGB(255,0,255));
		averageHullArea += getHullArea(blobToShow);
		shapeXCenters[numSymbols] = thisCenter;
		shapeYCenters[numSymbols] = blobToShow.sumy;
	}

	if (numSymbols) averageHullArea /= numSymbols;
*/

////////////////////////////////////////////////////////////////////////////////////////////////////////////

	//printf("end blob processing\n");
    /*
		 * DRAW THE IMAGES TO SCREEN
		 */
		if (drawingRectangle)  // shows a yellow rectangle when selecting a region
		  cvRectangle(outputImage, cvPoint(selection.x,selection.y),   // from here
                  cvPoint(selection.x+selection.width, selection.y+selection.height),  // to here
                  CV_RGB(255,255,0),1,8,0);  // yellow, 1 pixel thick, 8-connected
    
    //cvShowImage( "InputImage", inputImage );    // render the input image
    cvShowImage( "OutputImage", outputImage );  // render the output image
    //cvShowImage( "BinaryImage", binaryImage );  // render the binary image
    
	//printf("end drawing images\n");
    /*
     * HANDLE KEY PRESSES to an OpenCV window
     */
	char filename[255];
    char cchar = (char) cvWaitKey(10);   // waits for 10 ms to get a keypress
                                         // use cvWaitKey(0) in order to wait forever...
    if ( cchar == 27 )  break;           // breaks on ESCape key
    int imageNumber;					 // Allows us to save files 
    switch( cchar )                      // handle other key presses
    {        

      case ' ': // stop and get one more frame
      {
        captureStatus = ONEFRAME;
        //runAlgorithm = true;
        break;
      }
           
      case 'L': // restart live capturing
      {
        captureStatus = LIVE;
        printf("Getting one frame.\n");
        break;
      }

	 case 'C': // go to camera
	 {
		captureType = IMAGES_FROM_CAMERA;
		printf("Switching to Camera");
		break;
	  }
	 case 'F': // go to folder
	 {
		captureType = IMAGES_FROM_FOLDER;
		printf("Switching to Folder");
		break;
		}
        
      case 'R': // reset the current color definition
      {
        currentColorArray.reset();
		break;
      }
        
      case 'A': // turn on or off algorithm running
      {
        if (runAlgorithm) runAlgorithm = false;
        else runAlgorithm = true;
		printf("Algorithm Status is %d", runAlgorithm);
        break;
      }
      
      case 'B': //run backwards through the pictures
      {
        nextFileNumber = nextFileNumber - 2;
        if (nextFileNumber < 0) nextFileNumber = MAX_FILE_NUMBER;
        captureStatus = ONEFRAME;
        //runAlgorithm = true;
        break;
      }

	  case 'S': // save the current image
	 {
		sprintf(filename, "%stmp/image%04d.bmp", ROOT_FOLDER, imageNumber++);
		printf("Saving File: %s \n", filename);
		cvSaveImage(filename, inputImage);
	 }

	  /** Old loading code
	  case '1': // use alternate color defintions (Green)
	  {
		sprintf(fileish,"%s/colorDef%02d.txt", ROOT_FOLDER, 0); //shadowed
		currentColors[0].loadFromFile( fileish );
		sprintf(fileish,"%s/colorDef%02d.txt", ROOT_FOLDER, 1); //unshadowed
		currentColors[1].loadFromFile( fileish );
        break;
	  }
	  case '2': // use alternate color defintions (Blue)
	  {
		sprintf(fileish,"%s/colorDef%02d.txt", ROOT_FOLDER, 2); //shadowed
		currentColors[2].loadFromFile( fileish );
		sprintf(fileish,"%s/colorDef%02d.txt", ROOT_FOLDER, 3); //unshadowed
		currentColors[3].loadFromFile( fileish );
        break;
	  }
	  case '3': // use alternate color defintions (Yellow)
	  {
		sprintf(fileish,"%s/colorDef%02d.txt", ROOT_FOLDER, 4); //shadowed
		currentColors[4].loadFromFile( fileish );
		sprintf(fileish,"%s/colorDef%02d.txt", ROOT_FOLDER, 5); //unshadowed
		currentColors[5].loadFromFile( fileish );
        break;
	  }
	  case '4': // use alternate color defintions (Red)
	  {
		sprintf(fileish,"%s/colorDef%02d.txt", ROOT_FOLDER, 6); //shadowed
		currentColors[6].loadFromFile( fileish );
		sprintf(fileish,"%s/colorDef%02d.txt", ROOT_FOLDER, 7); //unshadowed
		currentColors[7].loadFromFile( fileish );
        break;
	  }**/

	case '0': // turns blobs on or off
	  {
		if (blobsAreOn)
			blobsAreOn = false;
		else blobsAreOn = true;
		break;
	   }

	 case 'P': // print current array
	 {
		currentColorArray.print();
		break;
	  }
	  
	  
	  case '!': // save alternate color array (Red)
	  {
		
		sprintf(filename, "%sredColorDef%d.txt", ROOT_FOLDER, COLOR_STEP_SIZE);
		currentColorArray.saveToFile( filename);
        break;
	  }
	  case '@': // save alternate color defintions (Yellow)
	  {
		sprintf(filename, "%syellowColorDef%d.txt", ROOT_FOLDER, COLOR_STEP_SIZE);
		currentColorArray.saveToFile( filename);
        break;

	  }
	  case '#': // save alternate color defintions (Blue)
	  {
		char filename[255];
		sprintf(filename, "%sblueColorDef%d.txt", ROOT_FOLDER, COLOR_STEP_SIZE);
		currentColorArray.saveToFile( filename);
        break;

	  }
	  case '$': // save alternate color defintions (Green)
	  {
		sprintf(filename, "%sgreenColorDef%d.txt", ROOT_FOLDER, COLOR_STEP_SIZE);
		currentColorArray.saveToFile( filename);
        break;

	  }
	  
	  case '%': // save alternate color defintions (Pink)
	  {
		sprintf(filename, "%spinkColorDef%d.txt", ROOT_FOLDER, COLOR_STEP_SIZE);
		currentColorArray.saveToFile( filename);
        break;

	  }
	  
	  case '1': // load alternate color array (Red)
	  {
		currentColorArray.reset();
		sprintf(filename, "%sredColorDef%d.txt", ROOT_FOLDER, COLOR_STEP_SIZE);
		currentColorArray.loadFromFile( filename);
        break;
	  }
	  case '2': // load alternate color array (Yellow)
	  {
		currentColorArray.reset();
		sprintf(filename, "%syellowColorDef%d.txt", ROOT_FOLDER, COLOR_STEP_SIZE);
		currentColorArray.loadFromFile( filename);
        break;
	  }
	  case '3': // load alternate color array (Blue)
	  {
		currentColorArray.reset();
		sprintf(filename, "%sblueColorDef%d.txt", ROOT_FOLDER, COLOR_STEP_SIZE);
		currentColorArray.loadFromFile( filename);
        break;	  }
	  case '4': // load alternate color array (Green)
	  {
		currentColorArray.reset();
		sprintf(filename, "%sgreenColorDef%d.txt", ROOT_FOLDER, COLOR_STEP_SIZE);
		currentColorArray.loadFromFile( filename);
        break;
	  }
	  
	  case '5': // load alternate color array (Pink)
	  {
		currentColorArray.reset();
		sprintf(filename, "%spinkColorDef%d.txt", ROOT_FOLDER, COLOR_STEP_SIZE);
		currentColorArray.loadFromFile( filename);
        break;
	  }
	  
	  case 'Z': // Reload color definitons
	  {
		tCAHandler();
		break;
	   }
	   
	   case '-': // remove pixels from current definiton
	   {
		if (removePixels)
			removePixels = false;
		else removePixels = true;
		break;
	   }
		 


      default:
        break;
    } // end of the keypress-handling switch statement
    
  } // end of the main image input - process - output loop
  
  /*
   * If we're here, some event triggered the main loop to quit
   */
  timeToQuitNow = 1;    // set our signal for the serverThread to quit
  
  printf("Main thread quitting...\n");

/**#ifdef MAC_OS
  sleep(1.0);             // give it a moment...
#endif
#ifdef WINDOWS_OS
  Sleep(1000);
#endif
**/
  
  /*
   * release the OpenCV resources
   */
  cvReleaseCapture(&capture);
  cvDestroyWindow( "InputImage" );
  cvDestroyWindow( "OutputImage" );
  cvDestroyWindow( "BinaryImage" );
  
  return 0;
}



