#include <iostream.h>
#include <stdio.h>
#include <string.h>
#include <conio.h>
#include <fstream.h>
#include "Face.h"
#include "Functions.h"
#include "Gdr.h"
#include "Image.h"
#include "Backend.h"
#include "Onpaint.h"
#include "Frontend.h"

// Important note
// The input of the network must be within 0 - 1.

// Ill further divide the recognize into functions later.
// for now i want u guys see if its working properly.

void main()
{
	GDIP g;
	g.Init();
//	bool Train;
		
	// To be called only if the trained files are missing.
	//TrainNetwork("eye","Eyes\\",22,"jpg",80,50,0.001,0.01,8);
	//Factor = 8 for eye.Hence it is not defined for finding eyes
	//	in the GetEyePos routine.
	
	/* The following is for eithr training or recognizing a face. */
	
	cout << "\n\t Do u want to train[t] or recognize[r] : " << endl;
	char ch = ' ';
	while(ch != 'r' && ch != 't' && ch != 'q')
	{
		ch = getch();
	}
	
	//char ch = 'r';
	if(ch == 't')
	{
		/*system("cls");
		cout << "\n\t Enter name of picture file : ";
		char Name[80];
		cin >> Name;*/
		for(int ii = 0;ii < 4;ii ++)
		{
			char Name [] = "Pics\\1.jpg";
			Name[5] = '1' + ii;

			int x1,x2,y1,y2;
			GetEyePos(x1,y1,x2,y2,Name);
			fstream f;
			f.open("Count.txt",ios :: in);
			int no;
			f >> no;
			f.close();
			no ++;
			f.open("Count.txt",ios :: out);
			f << no;
			f.close();
			char TNam[] = "Data\\";
			char No[4];
			itoa(no,No,10);
			strcat(TNam,No);
			strcat(TNam,".dat");
			f.open(TNam,ios :: out);
			f << x1 << "\n";
			f << y1 << "\n";
			f << x2 << "\n";
			f << y2 << "\n";
			f << Name;
			f.close();
		}
	}
	else
	if(ch == 'r')
	{
		fstream f;
		int n;
		f.open("Count.txt",ios :: in);
		f >> n;
		f.close();
		Network Eye1,Eye2;
		long N[] = {500 , 500 , 5};
		Eye1.Initialize(3);
		Eye2.Initialize(3);
		Eye1.Initialize(N,0.01);
		Eye2.Initialize(N,0.01);
		Network B[3];
		for(int k = 0;k < 3;k ++)
		{
			B[k].Initialize(3);
			B[k].Initialize(N,0.01);
		}
		Network Eb1,Eb2;
		Eb1.Initialize(3);
		Eb2.Initialize(3);
		Eb1.Initialize(N,0.01);
		Eb2.Initialize(N,0.01);
		GetFeatureNetwork(Eye1,Eye2,Eb1,Eb2,B,"Train.jpg");
		double Ereye1,Ereye2,Ereb1,Ereb2,Erb[3];	
		//Errors for teh different features.
		Layer I, O;
		I.Initialize(500,Sigmoid,DerSig);
		O.Initialize(5,Sigmoid,DerSig);	
			
		// Read the networks from their respective files.
		double * Err = new double [n];	// Store the 4 errors.
		for(k = 0;k < n;k ++)
		{
			cout << "\n Pic " << k + 1 << endl;
			
			// Read all the respective Networks.
			double St[5];
		
			// Find the pos of the eyes.
			int ex1,ex2,ey1,ey2;
			char Nam[80];
			char TNam[] = "Data\\";
			char No[4];
			itoa(k+1,No,10);
			strcat(TNam,No);
			strcat(TNam,".dat");
			f.open(TNam,ios :: in);
			f >> ex1;
			f >> ey1;
			f >> ex2;
			f >> ey2;
			f >> Nam;
			f.close();
			Face F;
			F.Initialize(Nam);
			
			int mx = (ex1 + ey1 + 80)/2;
			// Test these eyes with that of the saved data
			// and calculate the error.
			int * Pix = F.GetPixData(ex1,ey1,ex1 + 80,ey1 + 50);
			double v = 0;
			int x = 0;
			for(int i = 0;i < 500;i ++)
			{
				v = 0;
				for(int j = 0;j < 8;j ++)
				{
					v += Pix[x ++];
				}
				v /= 80000000;
				I.Set(i,v);
			}
			Eye1.SetInput(I);
			Eye1.CalcOutput();
			Eye1.GetOutput(O);
			
			// Reads the reference values from the stored file.
			// for calculating the error measures.

			ReadOutput("eye1.op",St);
			cout << "Eye 1 "<< endl;
			Ereye1 = 0;
			for(i = 0;i < 5;i ++)
			{
				Ereye1 += pow((St[i] - O.Get(i)),2);
			}

			delete [] Pix;
			// eye2
			Pix = F.GetPixData(ex2,ey2,ex2 + 80,ey2 + 50);
			v = 0;
			x = 0;
			for(i = 0;i < 500;i ++)
			{
				v = 0;
				for(int j = 0;j < 8;j ++)
				{
					v += Pix[x ++];
				}
				v /= 80000000;
				I.Set(i,v);
			}
			Eye2.SetInput(I);
			Eye2.CalcOutput();
			Eye2.GetOutput(O);
			cout << "Eye 2" << endl;
			ReadOutput("eye2.op",St);
			Ereye2 = 0;
			for(i = 0;i < 5;i ++)
			{
				Ereye2 += pow((St[i] - O.Get(i)),2);
			}

			// Now the blocks between the eyes.

			mx -= 40;
			int y = ey1;
			for(int l = 0;l < 3;l ++)
			{
				delete [] Pix;
				Pix = F.GetPixData(mx,y,mx + 80,y + 50);
				v = 0;
				x = 0;
				for(i = 0;i < 500;i ++)
				{
					v = 0;
					for(int j = 0;j < 8;j ++)
					{
						v += Pix[x ++];
					}
					v /= 80000000;
					I.Set(i,v);
				}
				B[l].SetInput(I);
				B[l].CalcOutput();
				B[l].GetOutput(O);
				char NN[]  = "b0.op";
				NN[1] = l + '0';
				ReadOutput(NN,St);
				cout << "Block " << l << endl;
				Erb[l] = 0;
				for(i = 0;i < 5;i ++)
				{
					Erb[l] += pow((St[i] - O.Get(i)),2);
				}
				y += 50;
			}
			// Now calculate the errors for the eye brows.
			
			delete [] Pix;
			Pix = F.GetPixData(ex1 - 10,ey1- 25,ex1 + 90,ey1 + 25);
			v = 0;
			x = 0;
			for(i = 0;i < 500;i ++)
			{
				v = 0;
				for(int j = 0;j < 10;j ++)
				{
					v += Pix[x ++];
				}
				v /= 100000000;
				I.Set(i,v);
			}
			Eb1.SetInput(I);
			Eb1.CalcOutput();
			Eb1.GetOutput(O);
			cout << "Eyebrow 1" << endl;
			ReadOutput("eb1.op",St);
			Ereb1 = 0;
			for(i = 0;i < 5;i ++)
			{
				Ereb1 += pow((St[i] - O.Get(i)),2);
			}
			//eyebrow 2
			delete [] Pix;
			Pix = F.GetPixData(ex2 - 10,ey2- 25,ex2 + 90,ey2 + 25);
			v = 0;
			x = 0;
			for(i = 0;i < 500;i ++)
			{
				v = 0;
				for(int j = 0;j < 10;j ++)
				{
					v += Pix[x ++];
				}
				v /= 100000000;
				I.Set(i,v);
			}
			Eb2.SetInput(I);
			Eb2.CalcOutput();
			Eb2.GetOutput(O);
			ReadOutput("eb2.op",St);
			Ereb2 = 0;
			cout << "Eyebrow 2" << endl;
			for(i = 0;i < 5;i ++)
			{
				Ereb2 += pow((St[i] - O.Get(i)),2);
			}
			// This routine is used to calculate the weighted error.
			// it is simple mathematics for now.
			// Got to train a network to get the probability.
			Err[k] = CalcError(Ereye1,Ereye2,Erb,Ereb1,Ereb2);
			f.open("Error.log",ios :: app);
			f << (k + 1) << "\n";
			f << Ereye1 << "\n";
			f << Ereye2 << "\n";
			f << Erb[0] << "\n";
			f << Erb[1] << "\n";
			f << Erb[2] << "\n";
			f << Ereb1 << "\n";
			f << Ereb2 << "\n";
			f.close();
		}
		int pos = 0;
		double E = 9999;
		for(k = 0;k < n;k ++)
		{
			if(Err[k] < E)
			{
				E = Err[k];
				pos = k;
			}
		}/*
		Eye1.DestroyAll();
		Eye2.DestroyAll();
		Eb1.DestroyAll();
		Eb2.DestroyAll();
		B[0].DestroyAll();
		B[1].DestroyAll();
		B[2].DestroyAll();*/
		cout << "The face belongs to pic " << pos << endl;
		delete []Err;
	}
	g.ShutDown();
	

}

// Get the 2 positions of the eye.

void GetEyePos(int &x1,int &y1,int &x2,int &y2,char Name [])
{
	ImageManip Im;
	Face F;
	Network EdgeEye,PixEye;
	long N[] = {500,500,5};
	double St[5],St1[5],E;
	int * Pix;
	
	Layer I;
	Layer O;
	I.Initialize(500,Sigmoid,DerSig);
	O.Initialize(5,Sigmoid,DerSig);

	EdgeEye.ReadFromFile("Nw\\Edgeeye.dat");
	PixEye.ReadFromFile("Nw\\Pixeye.dat");

	
	/* Get Standard reference values */

	int W,H;
	// this i feel is the most ideal eye in the set of eyes.
	Pix = Im.GetPixelData("Eyes\\12.jpg",W,H);
	
	int x = 0;
	double v;
	for(int j = 0;j < 500;j ++)
	{
		v = 0;
		for(int k = 0;k < 8;k ++)
		{
			v += Pix[x ++];
		}
		v /= 80000000;
		I.Set(j,v);
	}
	PixEye.SetInput(I);
	PixEye.CalcOutput();
	PixEye.GetOutput(O);
	for(int i = 0;i < 5;i ++)
	{
		St[i] = O.Get(i);
	}
	x = 0;
	Pix = Im.GetEdgeData(Pix,W,H);
	for(j = 0;j < 500;j ++)
	{
		int t = 0;
		v = 0;
		for(int k = 0;k < 8;k ++)
		{
			t = Pix[x ++];
			t = t << (7 - k); // making 8 values (0 / 1)into a byte.
			v += t;
		}
		v /= 1000;
		I.Set(j,v);
	}
	
	EdgeEye.SetInput(I);
	EdgeEye.CalcOutput();
	EdgeEye.GetOutput(O);
	for(i = 0;i < 5;i ++)
	{
		St1[i] = O.Get(i);
	}
	// st and st1 stores the reference values for pixel and edge networks.
	// used in calculating the errors.

	/* Search the Image for the Eyes  */
	
	F.Initialize(Name);
	double Er[9][8];	//Store the errors in each block(Edge net)
	for(i = 0;i < 72;i ++)//there are 72 blocks
	{
		if((i % 8) != 0 && (i % 8) != 7 && i < 48)// isearch for 2/3 of the face. and leave the 1st and last block
		{
			Pix = F.GetPixData(i,50,80);
			Pix = Im.GetEdgeData(Pix,80,50);
			int x = 0;
			double v;
			for(int j = 0;j < 500;j ++)
			{
				v = 0;
				int t = 0;
				for(int k = 0;k < 8;k ++)
				{
					t = Pix[x ++];
					t = t << (7 - k);//for compression
					v += t;
				}
				v /= 1000;
				I.Set(j,v);
			}
			EdgeEye.SetInput(I);
			EdgeEye.CalcOutput();
			EdgeEye.GetOutput(O);
			v = 0;
			for(j = 0;j < 5;j ++)
			{
				v += (St1[j] - O.Get(j)) * (St1[j] - O.Get(j));
			}
			Er[i / 8][i % 8] = v;
			delete []Pix;
		}
		else
		{
			Er[i / 8][i % 8] = 9999;//if its in a block i dont want to search.
		}// ie in the later 1/3 or the 1st or last block in each row.
		//cout << "Block : " << i << endl;
		cOnPaint.SetBlock((i % 8) * 80,(i / 8) * 50);
	}
	

	double Pr[9][8];	// Stores errors from each block.Her its the pixel network
	for(i = 0;i < 72;i ++)
	{
		if((i % 8) != 0 && (i % 8) != 7 && i < 48)
		{
			Pix = F.GetPixData(i,50,80);
			int x = 0;
			double v;
			for(int j = 0;j < 500;j ++)
			{
				v = 0;
				for(int k = 0;k < 8;k ++)
				{
					v += Pix[x ++];
				}
				v /= 80000000;	// to make i/p < 1
				I.Set(j,v);
			}
			PixEye.SetInput(I);
			PixEye.CalcOutput();
			PixEye.GetOutput(O);
			v = 0;
			for(j = 0;j < 5;j ++)
			{
				v += (St[j] - O.Get(j)) * (St[j] - O.Get(j));
			}
			Pr[i / 8][i % 8] = v;
			delete []Pix;
		}
		else
		{
			Pr[i / 8][i % 8] = 9999;
		}
		//cout << "Block : " << i << endl;
		cOnPaint.SetBlock((i % 8) * 80,(i / 8) * 50);
	}

	/* Now we are done with the searching */
	/* Find the min in both networks */

	
	/* here i follolow this simple algorithm.
		a block is an eye iff it satifies both edge and pixel network.
		hence i find the product of the min errors of both in each row
		and choose the product that is the lowest.
		1st i fine the least 2 in each row by the edge and multiply with 
		that of the pixel net for the same blocks.
		then its wrt pixel.
		I choose the least of the two.
	*/
	cOnPaint.SetBlock(-1,-1);
	int no,no1;
	double min = 9999999;
	for(i = 0;i < 9;i ++)
	{
		double m1 = 9999,m2 = 9999;
		int ii,jj;
		for(int j = 0;j < 8;j ++)
		{
			if(Er[i][j] < m2)
			{
				if(Er[i][j] < m1)
				{
					m2 = m1;
					m1 = Er[i][j];
					jj = ii;
					ii = j;
				}
				else
				{
					m2 = Er[i][j];
					jj = j;
				}
			}
		}
		if(Er[i][ii] * Er[i][jj] * Pr[i][ii] * Pr[i][jj] < min)
		{
			min = Er[i][ii] * Er[i][jj] * Pr[i][ii] * Pr[i][jj];
			no = i * 8 + ii;
			no1 = i * 8 + jj;
		}
		
		m1 = m2 = 9999;
		for(j = 0;j < 8;j ++)
		{
			if(Pr[i][j] < m2)
			{
				if(Pr[i][j] < m1)
				{
					m2 = m1;
					m1 = Pr[i][j];
					jj = ii;
					ii = j;
				}
				else
				{
					m2 = Pr[i][j];
					jj = j;
				}
			}
		}
		if(Er[i][ii] * Er[i][jj] * Pr[i][ii] * Pr[i][jj] < min)
		{
			min = Er[i][ii] * Er[i][jj] * Pr[i][ii] * Pr[i][jj];
			no = i * 8 + ii;
			no1 = i * 8 + jj;
		}
	}
	/* Here the minimum is that which is the minimum for the combined 
	   Network.Hence i multiply both the values and choose the one 
	   that has	the least for both combined */
	
	int y;
	double OE;
	if(no < no1)
		Swap(no,no1);
	y = no / 8 * 50;
	x = no % 8 * 80;

	/* Fine adjustments in anticlockwise direction */
	/* move block pixel by pixel to get the best position for the eyes.
	this i do because the blocks need not align properly with the eyes
	*/
	E = 9999;
	cout << "\n Normalizing Left " << endl;
	do
	{
		OE = E;
		x --;
		//cOnPaint.SetBlock(x,y);
		Pix = F.GetPixData(x,y,x + 80,y + 50);
		int ct = 0;
		for(int j = 0;j < 500;j ++)
		{
			v = 0;
			for(int k = 0;k < 8;k ++)
			{
				v += Pix[ct ++];
			}
			v /= 80000000;
			I.Set(j,v);
		}
		PixEye.SetInput(I);
		PixEye.CalcOutput();
		PixEye.GetOutput(O);
		OE = E;
		E = 0;
		for(i = 0;i < 5;i ++)
		{
			E += (St[i] - O.Get(i)) * (St[i] - O.Get(i));
		}
		Pix = Im.GetEdgeData(Pix,80,50);
		ct = 0;
		for(j = 0;j < 500;j ++)
		{
			v = 0;
			int t = 0;
			for(int k = 0;k < 8;k ++)
			{
				t = Pix[ct ++];
				t = t << (7 - k);
				v += t;
			}
			v /= 1000;
			I.Set(j,v);
		}
		EdgeEye.SetInput(I);
		EdgeEye.CalcOutput();
		EdgeEye.GetOutput(O);
		double Er = E;
		E = 0;
		for(i = 0;i < 5;i ++)
		{
			E += (St1[i] - O.Get(i)) * (St1[i] - O.Get(i));
		}	
		E *= Er;
		delete [] Pix;
	}while(OE > E);
	
	cout << "\n Normalizing Down " << endl;
	E = 9999;
	do
	{
		OE = E;
		y ++;
//		cOnPaint.SetBlock(x,y);
		Pix = F.GetPixData(x,y,x + 80,y + 50);
		int ct = 0;
		for(int j = 0;j < 500;j ++)
		{
			v = 0;
			for(int k = 0;k < 8;k ++)
			{
				v += Pix[ct ++];
			}
			v /= 80000000;
			I.Set(j,v);
		}
		PixEye.SetInput(I);
		PixEye.CalcOutput();
		PixEye.GetOutput(O);
		OE = E;
		E = 0;
		for(i = 0;i < 5;i ++)
		{
			E += (St[i] - O.Get(i)) * (St[i] - O.Get(i));
		}
		Pix = Im.GetEdgeData(Pix,80,50);
		ct = 0;
		for(j = 0;j < 500;j ++)
		{
			v = 0;
			int t = 0;
			for(int k = 0;k < 8;k ++)
			{
				t = Pix[ct ++];
				t = t << (7 - k);
				v += t;
			}
			v /= 1000;
			I.Set(j,v);
		}
		EdgeEye.SetInput(I);
		EdgeEye.CalcOutput();
		EdgeEye.GetOutput(O);
		double Er = E;
		E = 0;
		for(i = 0;i < 5;i ++)
		{
			E += (St1[i] - O.Get(i)) * (St1[i] - O.Get(i));
		}	
		E *= Er;
		delete [] Pix;
	}while(OE > E);

	cout << "\n Normalizing Right " << endl;
	E = 9999;
	do
	{
		OE = E;
		x ++;
//		cOnPaint.SetBlock(x,y);
		Pix = F.GetPixData(x,y,x + 80,y + 50);
		int ct = 0;
		for(int j = 0;j < 500;j ++)
		{
			v = 0;
			for(int k = 0;k < 8;k ++)
			{
				v += Pix[ct ++];
			}
			v /= 80000000;
			I.Set(j,v);
		}
		PixEye.SetInput(I);
		PixEye.CalcOutput();
		PixEye.GetOutput(O);
		OE = E;
		E = 0;
		for(i = 0;i < 5;i ++)
		{
			E += (St[i] - O.Get(i)) * (St[i] - O.Get(i));
		}
		Pix = Im.GetEdgeData(Pix,80,50);
		ct = 0;
		for(j = 0;j < 500;j ++)
		{
			v = 0;
			int t = 0;
			for(int k = 0;k < 8;k ++)
			{
				t = Pix[ct ++];
				t = t << (7 - k);
				v += t;
			}
			v /= 1000;
			I.Set(j,v);
		}
		EdgeEye.SetInput(I);
		EdgeEye.CalcOutput();
		EdgeEye.GetOutput(O);
		double Er = E;
		E = 0;
		for(i = 0;i < 5;i ++)
		{
			E += (St1[i] - O.Get(i)) * (St1[i] - O.Get(i));
		}	
		E *= Er;
		delete [] Pix;
	}while(OE > E);
		
	
	cout << "\n Normalizing Up " << endl;
	E = 9999;
	do
	{
		OE = E;
		y --;
//		cOnPaint.SetBlock(x,y);
		Pix = F.GetPixData(x,y,x + 80,y + 50);
		int ct = 0;
		for(int j = 0;j < 500;j ++)
		{
			v = 0;
			for(int k = 0;k < 8;k ++)
			{
				v += Pix[ct ++];
			}
			v /= 80000000;
			I.Set(j,v);
		}
		PixEye.SetInput(I);
		PixEye.CalcOutput();
		PixEye.GetOutput(O);
		OE = E;
		E = 0;
		for(i = 0;i < 5;i ++)
		{
			E += (St[i] - O.Get(i)) * (St[i] - O.Get(i));
		}
		Pix = Im.GetEdgeData(Pix,80,50);
		ct = 0;
		for(j = 0;j < 500;j ++)
		{
			v = 0;
			int t = 0;
			for(int k = 0;k < 8;k ++)
			{
				t = Pix[ct ++];
				t = t << (7 - k);
				v += t;
			}
			v /= 1000;
			I.Set(j,v);
		}
		EdgeEye.SetInput(I);
		EdgeEye.CalcOutput();
		EdgeEye.GetOutput(O);
		double Er = E;
		E = 0;
		for(i = 0;i < 5;i ++)
		{
			E += (St1[i] - O.Get(i)) * (St1[i] - O.Get(i));
		}	
		E *= Er;
		delete [] Pix;
	}while(OE > E);
	
	/* The Other Eye */
	
	x1 = x;
	y1 = y;
	int mx;

	mx = x1 - 70;
	x = x1 - 150;
	
	/* Assume that the eye is in tha same line as the other hence
	   Search only in the horozontal direction */
	
	E = 9999;
	cout << "\n Finding Second Eye " << endl;
	do
	{
		OE = E;
		x ++;
//		cOnPaint.SetBlock(x,y);
		Pix = F.GetPixData(x,y,x + 80,y + 50);
		int ct = 0;
		for(int j = 0;j < 500;j ++)
		{
			v = 0;
			for(int k = 0;k < 8;k ++)
			{
				v += Pix[ct ++];
			}
			v /= 80000000;
			I.Set(j,v);
		}
		PixEye.SetInput(I);
		PixEye.CalcOutput();
		PixEye.GetOutput(O);
		OE = E;
		E = 0;
		for(i = 0;i < 5;i ++)
		{
			E += (St[i] - O.Get(i)) * (St[i] - O.Get(i));
		}
		Pix = Im.GetEdgeData(Pix,80,50);
		ct = 0;
		for(j = 0;j < 500;j ++)
		{
			v = 0;
			int t = 0;
			for(int k = 0;k < 8;k ++)
			{
				t = Pix[ct ++];
				t = t << (7 - k);
				v += t;
			}
			v /= 1000;
			I.Set(j,v);
		}
		EdgeEye.SetInput(I);
		EdgeEye.CalcOutput();
		EdgeEye.GetOutput(O);
		double Er = E;
		E = 0;
		for(i = 0;i < 5;i ++)
		{
			E += (St1[i] - O.Get(i)) * (St1[i] - O.Get(i));
		}	
		E *= Er;
		delete [] Pix;
	}while(OE > E);// && x < mx);
	/* the 2 positions are stored. 1st eye is already in x1,y1.*/
	x2 = x;
	y2 = y;
	PixEye.DestroyAll();
	EdgeEye.DestroyAll();
}


/* Generic Function to train any network */

void TrainNetwork(char NameOfNetwork [],char Nam[],int Range,char Type[],int Width,int Height,double ThreshHold,double LRate,int Factor,int Startx,int Starty)
{
	Network EdgeNet;
	Network PixNet;
	ImageManip Im;
	long NoOfNeurons = Width * Height / Factor;	//Used for compressing the network
	long N[] = { NoOfNeurons , NoOfNeurons , 5 };
	EdgeNet.Initialize(3);
	EdgeNet.Initialize(N,LRate);

	PixNet.Initialize(3);
	PixNet.Initialize(N,LRate);
	
	Layer I;
	Layer O;
	I.Initialize(NoOfNeurons,Sigmoid,DerSig);
	O.Initialize(5,Sigmoid,DerSig);

	int * Pi,* Pix;
	for(int i = 0;i < 5;i ++)
	{
		O.Set(i,0.5);
	}
	i = 1;

	/* Train by the Edge */
	double E = 9999;
	/* Keep Training until all the trainsets have eror less than threshhold. */
	while(i <= Range || E > ThreshHold)
	{
		// Establish the name of the files.
		char Name[128];
		strcpy(Name,Nam);
		char No[3];
		i = i % (Range + 1);
		if(i == 0)
			i = 1;
		itoa(i,No,10);
		strcat(Name,No);
		strcat(Name,".");
		strcat(Name,Type);
		int W,H;
		Pi = Im.GetPixelData(Name,W,H);
		Pi = Im.GetEdgeData(Pi,W,H);
		Pix = new int [Width * Height];
		int x = 0;
		// Get the required pixels from the picture
		for(int j = Starty;j < Starty + Height;j ++)
		{
			for(int k = Startx;k < Startx + Width;k ++)
			{
				Pix[x ++] = Pi[j * Width + k];
			}
		}
		x = 0;
		double v;
		for(j = 0;j < NoOfNeurons;j ++)
		{
			int t = 0;
			v = 0;
			// used for compression.
			for(int k = 0;k < Factor;k ++)
			{
				t = Pix[x ++];
				t = t << (Factor - 1 - k);
				v += t;
			}
			v /= (pow(2,(Factor - 8)) * 1000);
			I.Set(j,v);
		}
		E = EdgeNet.Train(I,O,ThreshHold,0);
		i ++;
		cout << E << endl;
		if(Pix != NULL)
			delete []Pix;
		if(Pi != NULL)
			delete []Pi;
	}

	cout << "\n Training the pixel Network" << endl;
	
	E = 9999;
	i = 1;
	/* Keep Training until all the trainsets have eror less than threshhold. */
	while(i <= Range || E > ThreshHold)
	{
		char Name[128];
		strcpy(Name,Nam);
		char No[3];
		i = i % (Range + 1);
		if(i == 0)
			i = 1;
		itoa(i,No,10);
		strcat(Name,No);
		strcat(Name,".");
		strcat(Name,Type);
		int W,H;
		Pi = Im.GetPixelData(Name,W,H);
		int x = 0;
		Pix = new int [Width * Height];
		for(int j = Starty;j < Starty + Height;j ++)
		{
			for(int k = Startx;k < Startx + Width;k ++)
			{
				Pix[x ++] = Pi[j * Width + k];
			}
		}
		x = 0;
		double v;
		for(j = 0;j < NoOfNeurons;j ++)
		{
			v = 0;
			// Used for compression.
			for(int k = 0;k < Factor;k ++)
			{
				v += Pix[x ++];
			}
			v /= (pow(2,Factor - 8) * 10000000);
			I.Set(j,v);
		}
		E = PixNet.Train(I,O,ThreshHold,0);
		i ++;
		cout << E << endl;
		if(Pix != NULL)
			delete []Pix;
		if(Pi != NULL)
			delete []Pi;
	}

	/* Now Saving the 2 networks */

	char Name[128];
	strcpy(Name,"Nw\\Edge");
	strcat(Name,NameOfNetwork);
	strcat(Name,".dat");
	EdgeNet.WriteToFile(Name);
	strcpy(Name,"Nw\\Pix");
	strcat(Name,NameOfNetwork);
	strcat(Name,".dat");
	PixNet.WriteToFile(Name);
}


void StoreOutput(Network & N,Layer & I,char OpName[])
{
	Layer O;
	O.Initialize(3,Sigmoid,DerSig);
	
	N.SetInput(I);
	N.CalcOutput();
	N.GetOutput(O);
	/* JUST CALCULATE THE OP FOR A inpout and store it in a file */
	fstream f;
	f.open(OpName,ios :: out);
	for(int i = 0;i < 5;i ++)
	{
		f << O.Get(i);
	}
	f.close();
}

void ReadOutput(char Name[],double P[])
{
	fstream f;
	f.open(Name,ios :: in);
	for(int i = 0;i < 5;i ++)
	{
		double v;
		f >> v;
		P[i] = v;
	}
	f.close();
	/* read the op from a file */
}

double CalcError(double Ereye1,double Ereye2,double Eeb [],double Ereb1,double Ereb2)
{
	double E = Ereye1 * Ereye2;
	E = sqrt(E);
	double E1 = Ereb1 * Ereb2;
	E1 = sqrt(E1);
	double E2 = (Eeb[0] + Eeb[1] + Eeb[2])/3;
	E2 /= 100;
	E += E1 + E2;
	return E;
	/* i assume eye has most prominence followed by eyebrowsand hence 
	found the geometric mean for them and the nose region only the 
	arithmetic mean. */
}

void GetFeatureNetwork(Network & Eye1,Network & Eye2,Network &Eb1,Network &Eb2,Network B[],char Name[])
{
	// I assume 1 pic is enough for the training set 
	// Its named Train.jpg in the same directory;
	Face F;
		
	Layer I,O;
	I.Initialize(500,Sigmoid,DerSig);
	O.Initialize(5,Sigmoid,DerSig);
	
	//Set  teh O/p valuses
	for(int i = 0;i < 5;i ++)
	{
		O.Set(i,0.5);
	}
	
	F.Initialize(Name);
	int ex1,ey1,ex2,ey2;
	GetEyePos(ex1,ey1,ex2,ey2,Name);
	int mx = (ex1 + ex2 + 80)/2;	// Mid point.
	// Used for the 3 blocks between the eyes.
	int * Pix;
	long N[] = {500,500,5};
	// Store 2 Networks specialized for the 2 eyes
	Pix = F.GetPixData(ex1,ey1,ex1 + 80,ey1 + 50);
	double v = 0;
	int x = 0;
	// Read the values,compress it and store it in layer I.(ip)
	for(i = 0;i < 500;i ++)
	{
 		v = 0;
		for(int j = 0;j < 8;j ++)
		{
			v += Pix[x ++];
		}
		v /= 80000000;
		I.Set(i,v);
	}
	Ctrs.PostStatMsg("Training left eye network");
	Eye1.Train(I,O,0.001);
	// Stores the reference o/p values in a file
	// Named it .op just for the heck of it.
	StoreOutput(Eye1,I,"eye1.op");
	delete [] Pix;
	// 2nd eye
	Pix = F.GetPixData(ex2,ey2,ex2 + 80,ey2 + 50);
	v = 0;
	x = 0;
	// compress
	for(i = 0;i < 500;i ++)
	{
		v = 0;
		for(int j = 0;j < 8;j ++)
		{
			v += Pix[x ++];
		}
		v /= 80000000;
		I.Set(i,v);
	}
	Ctrs.PostStatMsg("Training eight eye network");
	Eye2.Train(I,O,0.001);
	StoreOutput(Eye2,I,"eye2.op");
	// Store 3 networks for blocks between eyes.
	mx -= 40;
	int y = ey1;
	for(int k = 0;k < 3;k ++)
	{
		delete [] Pix;
		Pix = F.GetPixData(mx,y,mx + 80,y + 50);
		v = 0;
		x = 0;
		for(i = 0;i < 500;i ++)
		{
			v = 0;
			for(int j = 0;j < 8;j ++)
			{
				v += Pix[x ++];
			}
			v /= 80000000;
			I.Set(i,v);
		}
		Ctrs.StatPrintf("Training nose network %d",k);
		B[k].Train(I,O,0.001);
		char NN[] = "b0.op";
		NN[1] = '0' + k;
		StoreOutput(B[k],I,NN);
		y += 50;
	}
	// Now Train for the 2 eyebrows.
	//the eyebrow block i assume overlaps with the eyes.
		
	delete [] Pix;
	// due to the overlapping i assume it is half way above the eye
	// Hence it eye -25 to eye + 25.
	// ive given it extra width.(100)
	Pix = F.GetPixData(ex1 - 10,ey1 - 25,ex1 + 90,ey1 + 25);
	v = 0;
	x = 0;
	for(i = 0;i < 500;i ++)
	{
		v = 0;
		for(int j = 0;j < 10;j ++)
		{
			v += Pix[x ++];
		}
		v /= 100000000;
		I.Set(i,v);
	}
	Ctrs.PostStatMsg("Training left eyebrow network");
	Eb1.Train(I,O,0.001);
	StoreOutput(Eb1,I,"eb1.op");
	delete [] Pix;
	//2nd eyebrow.
	Pix = F.GetPixData(ex2 - 10,ey2- 25,ex2 + 90,ey2 + 25);
	v = 0;
	x = 0;
	for(i = 0;i < 500;i ++)
	{
		v = 0;
		for(int j = 0;j < 10;j ++)
		{
			v += Pix[x ++];
		}
		v /= 100000000;
		I.Set(i,v);
	}
	Ctrs.PostStatMsg("Training right eyebrow network");
	Eb2.Train(I,O,0.001);
	StoreOutput(Eb2,I,"eb2.op");
	delete []Pix;
	//Now Save all the networks in a file;
/*	Eye1.WriteToFile("eye1.dat");
	Eye2.WriteToFile("eye2.dat");
		for(i = 0;i < 3;i ++)
		{
			char NN[] = "B0.dat";
			NN[1] = '0' + i;
			B[i].WriteToFile(NN);
		}
		Eb1.WriteToFile("eb1.dat");
		Eb2.WriteToFile("eb2.dat");
	}*/
}
	

void BTrain(char Folder[])
{
	char Name[80];
	strcpy(Name,Folder);
	strcat(Name,"\\Train.jpg");
	int x1,x2,y1,y2;
	GetEyePos(x1,y1,x2,y2,Name);
	fstream f;
	strcpy(Name,Folder);
	strcat(Name,"\\Feature.dat");
	f.open(Name,ios :: out);
	f << x1 << "\n";
	f << y1 << "\n";
	f << x2 << "\n";
	f << y2 << "\n";
	f.close();
}

void BRecog(char Person[])
{
	cOnPaint.OnRecogInit();

	fstream f;
	char Name[80];
	int n;
	f.open("Train\\Trained.txt",ios :: in);
	if(!f)
		return;
	n = 0;
	while(!f.eof())
	{
		f.getline(Name,80);
		n ++;
	}
	n --;
	f.close();
	f.open("Train\\Trained.txt",ios :: in);
	Network Eye1,Eye2;
	long N[] = {500 , 500 , 5};
	Eye1.Initialize(3);
	Eye2.Initialize(3);
	Eye1.Initialize(N,0.01);
	Eye2.Initialize(N,0.01);
	Network B[3];
	
	int k;

	for(k = 0;k < 3;k ++)
	{
		B[k].Initialize(3);
		B[k].Initialize(N,0.01);
	}
	Network Eb1,Eb2;
	Eb1.Initialize(3);
	Eb2.Initialize(3);
	Eb1.Initialize(N,0.01);
	Eb2.Initialize(N,0.01);
	fstream ff;
	// Error Correction
	ff.open("Recog.jpg",ios :: in);
	if(!ff)
		return;
	ff.close();

	GetFeatureNetwork(Eye1,Eye2,Eb1,Eb2,B,"Recog.jpg");
	double Ereye1,Ereye2,Ereb1,Ereb2,Erb[3];	
	//Errors for teh different features.
	Layer I, O;
	I.Initialize(500,Sigmoid,DerSig);
	O.Initialize(5,Sigmoid,DerSig);	
		
	// Read the networks from their respective files.
	double * Err = new double [n];	// Store the 4 errors.
	k = 0;
	while(!f.eof())
	{
		cout << "\n Pic " << k + 1 << endl;
		// Read all the respective Networks.
		double St[5];
	
		// Find the pos of the eyes.
		int ex1,ex2,ey1,ey2;
		char Nam[80];
		char TNam[80];
		f.getline(TNam,80);
		if(f.eof())
			break;
		sprintf(Nam,"Train\\%s\\Train.jpg",TNam);
		char Dat[80];
		sprintf(Dat,"Train\\%s\\Feature.dat",TNam);
		ff.open(Dat,ios :: in);
		ff >> ex1;
		ff >> ey1;
		ff >> ex2;
		ff >> ey2;
		ff.close();
		Face F;
		F.Initialize(Nam);

		// Report the file name we trying to match
		cOnPaint.Matching(Nam);
		
		int mx = (ex1 + ex2 + 80)/2;
		// Test these eyes with that of the saved data
		// and calculate the error.
		int * Pix = F.GetPixData(ex1,ey1,ex1 + 80,ey1 + 50);
		double v = 0;
		int x = 0;
		for(int i = 0;i < 500;i ++)
		{
			v = 0;
			for(int j = 0;j < 8;j ++)
			{
				v += Pix[x ++];
			}
			v /= 80000000;
			I.Set(i,v);
		}
		Eye1.SetInput(I);
		Eye1.CalcOutput();
		Eye1.GetOutput(O);
		
		// Reads the reference values from the stored file.
		// for calculating the error measures.
		ReadOutput("eye1.op",St);
		cout << "Eye 1 "<< endl;
		Ereye1 = 0;
		for(i = 0;i < 5;i ++)
		{
			Ereye1 += pow((St[i] - O.Get(i)),2);
		}
		delete [] Pix;
		// eye2
		Pix = F.GetPixData(ex2,ey2,ex2 + 80,ey2 + 50);
		v = 0;
		x = 0;
		for(i = 0;i < 500;i ++)
		{
			v = 0;
			for(int j = 0;j < 8;j ++)
			{
				v += Pix[x ++];
			}
			v /= 80000000;
			I.Set(i,v);
		}
		Eye2.SetInput(I);
		Eye2.CalcOutput();
		Eye2.GetOutput(O);
		cout << "Eye 2" << endl;
		ReadOutput("eye2.op",St);
		Ereye2 = 0;
		for(i = 0;i < 5;i ++)
		{
			Ereye2 += pow((St[i] - O.Get(i)),2);
		}
		// Now the blocks between the eyes.
		mx -= 40;
		int y = ey1;
		for(int l = 0;l < 3;l ++)
		{
			delete [] Pix;
			Pix = F.GetPixData(mx,y,mx + 80,y + 50);
			v = 0;
			x = 0;
			for(i = 0;i < 500;i ++)
			{
				v = 0;
				for(int j = 0;j < 8;j ++)
				{
					v += Pix[x ++];
				}
				v /= 80000000;
				I.Set(i,v);
			}
			B[l].SetInput(I);
			B[l].CalcOutput();
			B[l].GetOutput(O);
			char NN[]  = "b0.op";
			NN[1] = l + '0';
			ReadOutput(NN,St);
			cout << "Block " << l << endl;
			Erb[l] = 0;
			for(i = 0;i < 5;i ++)
			{
				Erb[l] += pow((St[i] - O.Get(i)),2);
			}
			y += 50;
		}
		// Now calculate the errors for the eye brows.
			
		delete [] Pix;
		Pix = F.GetPixData(ex1 - 10,ey1- 25,ex1 + 90,ey1 + 25);
		v = 0;
		x = 0;
		for(i = 0;i < 500;i ++)
		{
			v = 0;
			for(int j = 0;j < 10;j ++)
			{
				v += Pix[x ++];
			}
			v /= 100000000;
			I.Set(i,v);
		}
		Eb1.SetInput(I);
		Eb1.CalcOutput();
		Eb1.GetOutput(O);
		cout << "Eyebrow 1" << endl;
		ReadOutput("eb1.op",St);
		Ereb1 = 0;
		for(i = 0;i < 5;i ++)
		{
			Ereb1 += pow((St[i] - O.Get(i)),2);
		}
		//eyebrow 2
		delete [] Pix;
		Pix = F.GetPixData(ex2 - 10,ey2- 25,ex2 + 90,ey2 + 25);
		v = 0;
		x = 0;
		for(i = 0;i < 500;i ++)
		{
			v = 0;
			for(int j = 0;j < 10;j ++)
			{
				v += Pix[x ++];
			}
			v /= 100000000;
			I.Set(i,v);
		}
		Eb2.SetInput(I);
		Eb2.CalcOutput();
		Eb2.GetOutput(O);
		ReadOutput("eb2.op",St);
		Ereb2 = 0;
		cout << "Eyebrow 2" << endl;
		for(i = 0;i < 5;i ++)
		{
			Ereb2 += pow((St[i] - O.Get(i)),2);
		}
		// This routine is used to calculate the weighted error.
		// it is simple mathematics for now.
		// Got to train a network to get the probability.
		Err[k ++] = CalcError(Ereye1,Ereye2,Erb,Ereb1,Ereb2);

		fstream ErrLg;

		ErrLg.open("Error.log",ios :: app);
		ErrLg << (k + 1) << "\n";
		ErrLg << Ereye1 << "\n";
		ErrLg << Ereye2 << "\n";
		ErrLg << Erb[0] << "\n";
		ErrLg << Erb[1] << "\n";
		ErrLg << Erb[2] << "\n";
		ErrLg << Ereb1 << "\n";
		ErrLg << Ereb2 << "\n";

		ErrLg.close();
	}
	int pos = 0;
	double E = 9999;
	for(k = 0;k < n;k ++)
	{
		if(Err[k] < E)
		{
			E = Err[k];
			pos = k;
		}
	}/*
	Eye1.DestroyAll();
	Eye2.DestroyAll();
	Eb1.DestroyAll();
	Eb2.DestroyAll();
	B[0].DestroyAll();
	B[1].DestroyAll();
	B[2].DestroyAll();*/
	delete []Err;
	f.close();
	f.open("Train\\Trained.txt",ios :: in);
	k = 0;
	while(k < pos)
	{
		f.getline(Name,80);
		k ++;
	}
	f.getline(Person,80);
	f.close();

	system("del *.op");
}