package main;

import hypothesis_validation.HoG_Functions;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.ArrayList;
import javax.imageio.ImageIO;
import parameters.detection_arguments;
import parameters.io_arguments;
import parameters.tracking_arguments;
import particlefiltering.particle;
import particlefiltering.particles;
import particlefiltering.pfTracking;
import preprocessing.Util;
import tracking.Atributes;
import xml.Icdar;
import association.HungarianAlgorithm;
import association.Probabilities;
import classification.SVM;
import classification.SVM_DATA;
import descriptors.HoG;
import fr.lip6.classifier.SMOSVM;

public class TextTracking {
	
	static double seconds = 0.0;
	
	public static void Tracking ( 
			ArrayList<SVM> svm_descriptors, 
			ArrayList<SVM_DATA> svm_classifiers,
			ArrayList<Double> HoG_mean,
			ArrayList<Double> HoG_std,
			io_arguments io_parameters, 
			detection_arguments detection_parameters) 
	throws FileNotFoundException, ClassNotFoundException, IOException  {

		tracking_arguments tracking_parameters = new tracking_arguments(io_parameters.get_tracking_parameters_file());
		
		ArrayList<Atributes> set_T = new ArrayList<Atributes>();

		ArrayList<particle[]> particles_list = new ArrayList<particle[]>();

		int label = 0;

		for (int iframe = io_parameters.get_bframe(); iframe <= io_parameters.get_eframe(); iframe++) {
			
			System.out.printf("Frame : %d\n", iframe);

			boolean detection = false;

			/*Creating sub-diretories (for each frame) to store the detection and tracking results*/
			File directory = new File (io_parameters.get_out_path() + String.format("%06d", iframe));
			directory.mkdir();

			/*Getting the image frame name*/
			String sframe_act = io_parameters.get_frames_path() + String.format("%06d", iframe) + ".png";
			String sframe_nxt = io_parameters.get_frames_path() + String.format("%06d", iframe+1) + ".png";
			
			/*Reading the image frames*/
			BufferedImage frame = null, tmp = null;
			
			try {
				frame = ImageIO.read(new File(sframe_act));
				tmp = ImageIO.read(new File(sframe_nxt));
			}
			catch (Exception e) {
				e.printStackTrace();
				System.exit(1);
			}		
			
			io_parameters.set_xml_header(String.format("%06d", iframe));
			
			if (  ( (iframe % io_parameters.get_tracking_step() ) == 0) || ( iframe == io_parameters.get_bframe() )  ) {

				//set_T.clear();
				
				/*Text Detection*/
				detection = true;
				
				/*Reseting the detection parameters*/
				detection_parameters = new detection_arguments(io_parameters.get_detection_parameters_file());
				
				/*Creating the Detected Set*/
				ArrayList<Atributes> set_D = new ArrayList<Atributes>();
				
				/*Performing Text Detection*/
				set_D = TextDetection.Detection (frame, svm_descriptors, svm_classifiers, HoG_mean, HoG_std, io_parameters, detection_parameters);

				System.out.printf("Antes de entrar aqui 2\n");
				
				BufferedImage porcaria = Util.imageScale (frame, 1.0);
				for (int index = 0; index < set_D.size(); index++) {
					Atributes lala = set_D.get (index);
					particles P = new particles();
					P.display_atribute (porcaria, lala, index);
				}
				try {
					ImageIO.write(porcaria, "png", new File(io_parameters.get_out_path() + String.format("%06d", iframe) + "/detection_numbered.png"));
				}
				catch (Exception e) {
					e.printStackTrace();
					System.exit(1);
				}
				System.out.printf("Antes de entrar aqui 4\n");
				
				
				System.out.printf("Detected boxes, size : %d\n", set_D.size());
				for (int index = 0; index < set_D.size(); index++) {
					Atributes lala = set_D.get (index);
					System.out.printf("index : %d, x : %f, y : %f,  w : %d, h: %d, weight : %f\n", index, lala.get_x(), lala.get_y(), lala.get_width(), lala.get_height(), lala.get_weight());
				}
				
				System.out.printf("Tracked boxes, size : %d\n", set_T.size());
				for (int index = 0; index < set_T.size(); index++) {
					Atributes lala = set_T.get (index);
					System.out.printf("index : %d, x : %f, y : %f, w : %d, h : %d, weight : %f\n", index, lala.get_x(), lala.get_y(), lala.get_width(), lala.get_height(), lala.get_weight());
				}
				
				/*Writing detection results*/
				write_set_regions (frame, set_D, io_parameters, false, iframe);
				
				/*Clean all the particles tracked before */// -> VERIFICAR
				//particles_list.clear();

				boolean transpose = false; 

				/*-------------------------------------------*/
				System.out.printf("Antes de entrar aqui 3\n");
				

				if (set_T.size() != 0) {
					
					System.out.printf("Dentro da codicao1\n");

					/*Computing the likelihood probability matrix between the detected {set_D} and tracked {set_T} sets*/
					if (set_D.size() != 0) {
						
						System.out.printf("Dentro da codicao2\n");

						double[][] P = new double[set_T.size()][set_D.size()];

						for (int i = 0; i < set_T.size(); i++) {

							Atributes Ti = set_T.get (i);

							for (int j = 0; j < set_D.size(); j++) {

								Atributes Dj = set_D.get (j);

								Probabilities Pr = new Probabilities();

								/*Frobenius product between the probabilities*/
								P[i][j] = Pr.prob_size (Ti, Dj, tracking_parameters) * Pr.prob_pos (Ti, Dj, tracking_parameters) * Pr.prob_app (Ti, Dj, tracking_parameters, iframe, i, j, io_parameters.get_xml_header());
								System.out.printf("prob[%d][%d] = %f (Probs: %f, %f, %f)\n", i, j, P[i][j], Pr.prob_size (Ti, Dj, tracking_parameters), Pr.prob_pos (Ti, Dj, tracking_parameters), Pr.prob_app (Ti, Dj, tracking_parameters, iframe, i, j, io_parameters.get_xml_header()));
								//System.err.printf("prob[%d][%d] = %f (Probs: %f, %f, %f)\n", i, j, P[i][j], Pr.prob_size (Ti, Dj, tracking_parameters), Pr.prob_pos (Ti, Dj, tracking_parameters), Pr.prob_app (Ti, Dj, tracking_parameters));
							}
						}
						
						for (int i = 0; i < set_T.size(); i++) {
							for (int j = 0; j < set_D.size(); j++) {
								System.out.printf("%f ", P[i][j]);
							}
							System.out.printf("\n");
						}

						System.err.printf("Antes de entrar aqui 5\n");
						/*-------------------------------------------*/

						/*Applying Hungarian algorithm, to create the list of best assignments*/
						HungarianAlgorithm HA = new HungarianAlgorithm();

						if (P.length > P[0].length) {
							P = HA.transpose(P);
							transpose = true;
						}

						int[][] A = new int[P.length][2];

						/*Getting the list of assignments*/
						A = HA.hgAlgorithm (P, "max"); 

						/*-------------------------------------------*/
						/*For those elements in {set_T} that have an association in {set_D} increase its weights*/
						for (int i = 0; i < A.length; i++) {
							if (P[A[i][0]][A[i][1]] > tracking_parameters.assignment_threshold) {
								System.out.printf("###################### A.LENGHT = %d\n", A.length);
								if (transpose) {
									Atributes Ti = set_T.get(A[i][1]);
									Ti.set_weight(1.0);

									Atributes Di = set_D.get(A[i][0]);
									Di.set_flag(true);

									/*Update the coordinates of the matched box*/
									Update_Coordinates (Ti, Di);
									
									System.out.printf("1 ###################### Entrei AQUI\n");
								}
								else {
									Atributes Ti = set_T.get(A[i][0]);
									Ti.set_weight(1.0);

									Atributes Di = set_D.get(A[i][1]);
									Di.set_flag(true);
									
									/*Update the coordinates of the matched box*/
									Update_Coordinates (Ti, Di);

									System.out.printf("2 ###################### Entrei AQUI\n");
								}
							}
						}
						System.out.printf("Antes de entrar aqui 6\n");
					} /*End Set_D != 0*/
					/*-------------------------------------------*/

					/*For those elements in {set_T} that have weight less than {kappa} remove them*/
					for (int i = 0; i < set_T.size(); i++) {
						Atributes E = set_T.get(i);
						System.out.printf("Elemento : %d, x : %f, y : %f, w :%d, h : %d, peso : %f\n", i, E.get_x(), E.get_y(), E.get_width(), E.get_height(), E.get_weight());
						if (E.get_weight() < tracking_parameters.weight_threshold) {
							System.out.printf("Eliminei elemento : %d, x : %f, y : %f, w :%d, h : %d\n", i, E.get_x(), E.get_y(), E.get_width(), E.get_height());
							set_T.remove(i);
						}
					} 
					System.out.printf("Antes de entrar aqui 7\n");
				}/*End Set_T != 0*/

				/*For those elements in {set_D} that do not have an association in {set_T} insert them*/
				for (int i = 0; i < set_D.size(); i++) {
					
					Atributes E = set_D.get (i);
					
					System.out.printf("Verificando elemento : %d, x : %f, y : %f, w :%d, h : %d\n", i, E.get_x(), E.get_y(), E.get_width(), E.get_height());
					
					if (!E.get_flag()) {
						
						System.out.printf("Inserido\n");
						
						/*Setting the weight of the new detected text region element to -INF*/
						E.set_weight (-Double.MIN_VALUE); 
						
						E.set_fp(0); //ANALISAR
						
						/*Setting the label of the new detected text region element*/
						E.set_label(String.valueOf(label));
						
						/*Inserting the new detected text region element*/
						set_T.add(E);
					
						/*Updating the number of text region labels*/
						label++;
					}
				}
				System.out.printf("Antes de entrar aqui 8\n");
			}

			/*Tracking with Particle Filters*/
			//System.out.printf("Antes de entrar aqui 9\n");
			//particles_list = PF (iframe, tmp, set_T, particles_list, HoG_mean, HoG_std, io_parameters, detection, detection_parameters, tracking_parameters); 
			
			particles_list = PF (iframe, tmp, set_T, particles_list, detection, io_parameters.get_out_path(), tracking_parameters); 				
			
			System.out.printf("Tracking - frame : %d\n\n", iframe);
		}
		System.out.println("Tracking (time - seconds): " + seconds/(io_parameters.get_eframe()+1));
	}
	
	static void Update_Coordinates (Atributes T, Atributes D) {
		
		int option = 2;
		
		//double factor = 0.6;
		
		/*Let the tracked coordinates and ignore the coordinates of the detected box*/
		if (option == 0) { 
			/*Nothing*/
		}
		/*Use the coordinates of the new detection and ignore the update box positions done by the tracking*/
		else if (option == 1) {
			T.set_x(D.get_x());
			T.set_y(D.get_y());
			T.set_width(D.get_width());
			T.set_height(D.get_height());
		}
		/*Uses the mean values of the detected and tracked boxes*/
		else if (option == 2) {
			T.set_x((D.get_x()+T.get_x())/2.0);
			T.set_y((D.get_y()+T.get_y())/2.0);
			T.set_width((int)((D.get_width()+T.get_width())/2));
			T.set_height((int)((D.get_height()+T.get_height())/2));
		}
		T.set_fp(0);
		/*Uses the mean values of the detected and tracked boxes*/
		/*else if (option == 3) {
			T.set_x((factor*D.get_x()+(1.0-factor)*T.get_x())/2.0);
			T.set_y((factor*D.get_y()+(1.0-factor)*T.get_y())/2.0);
			T.set_width((int)((factor*D.get_width()+(1.0-factor)*T.get_width())/2));
			T.set_height((int)((factor*D.get_height()+(1.0-factor)*T.get_height())/2));
		}*/
	}
	
	static ArrayList<particle[]> PF_ORIG ( 
			int iframe,
			BufferedImage image,
			ArrayList<Atributes> set_T,
			ArrayList<particle[]> particles_list,
			ArrayList<Double> hogmean, 
			ArrayList<Double> hogstd, 
			io_arguments io_parameters,
			boolean detection,
			detection_arguments detection_parameters,
			tracking_arguments tracking_parameters) throws FileNotFoundException, ClassNotFoundException, IOException  
			{
		
		BufferedImage tmp = Util.imageScale (image, 1.0);
		
		/*HoG*/
		SMOSVM<double[]> cls = null;
		try {
    		ObjectInputStream obj = new ObjectInputStream(new FileInputStream(detection_parameters.hog));
    	    cls = (SMOSVM<double[]>) obj.readObject();
    	    obj.close();
    	}
    	catch (Exception e){
    		e.printStackTrace();
    	}
		long start = System.currentTimeMillis();

		//int number_of_elements = 0;

		//double ft = 0.0;

		pfTracking pf = new pfTracking();

		//particles_list = new ArrayList<particle[]>();
		
		try {
			ImageIO.write(image, "png", new File(io_parameters.get_out_path() + String.format("%05d", iframe) + "/antes_tracking.png"));
		}
		catch (Exception e) {
			e.printStackTrace();
			System.exit(1);
		}

		if (detection) {

			particles_list = new ArrayList<particle[]>();
			
			System.err.printf("entrei aqui deteccao\n");
			
			//particles_list.clear();
			
			System.err.printf("Antes : o particle list tem tamanho de %d\n", particles_list.size());
			System.out.printf("Antes : o particle list tem tamanho de %d\n", particles_list.size());
			System.out.printf("Antes : o tamanho do conjunto T est %d\n", set_T.size());
			
			for (int i = 0; i < set_T.size(); i++) {

				Atributes E = set_T.get(i);

				pf.Initialization(E.image, (int)(E.get_x()), (int)(E.get_y()), E.get_width(), E.get_height(), particles_list, i, tracking_parameters);

				System.out.printf("Vou realizar particula com : %f %f %d %d\n", E.get_x(), E.get_y(), E.get_width(), E.get_height()); 
				
				//number_of_elements++;
			}
			System.err.printf("Depois : o particle list tem tamanho de %d\n", particles_list.size());
			System.out.printf("Depois : o particle list tem tamanho de %d\n", particles_list.size());
		}

		/*System.err.printf("Number of elements : %d, particles_list size : %d\n", number_of_elements, particles_list.size());
		
		for (int i = 0; i < particles_list.size(); i++) {
			particle[] p = particles_list.get(i);
			for(int j = 0; j < number_of_particles; j++ ) {
				System.err.printf("particula %d, x: %d\n", j, p[j].get_x());
			}
		}*/
		
		pf.Tracking (image, particles_list, particles_list.size(), iframe, tracking_parameters);

		
		System.out.printf("O tamanho de particulas eh : %d, o tamanho de set eh : %d\n", particles_list.size(), set_T.size());
		//System.out.printf("Depois do tracking\n"); 
		
		boolean[] remove = new boolean[set_T.size()];
		for (int i = 0; i < set_T.size(); i++) { remove[i] = false; } 
		
		for (int i = 0; i < set_T.size(); i++) {
			
			//System.out.printf("Dentro do for \n"); 

			Atributes E = set_T.get(i);

			HoG dhog = new HoG();

			/*double p_x = particles_list.get(i)[0].get_x();

			double p_y = particles_list.get(i)[0].get_y();

			double p_s = particles_list.get(i)[0].get_s();

			int p_w = particles_list.get(i)[0].get_width();

			int p_h = particles_list.get(i)[0].get_height();

			int x0 = Math.round( (float)(p_x - 0.5 * p_s * p_w) );

			int y0 = Math.round( (float)(p_y - 0.5 * p_s * p_h) );

			int x1 = Math.round( (float)(p_s * p_w) );

			int y1 = Math.round( (float)(p_s * p_h) );*/

			
			double s = particles_list.get(i)[0].get_s();
			int w_r = Math.round((float)(particles_list.get(i)[0].get_y())); 
            int w_c = Math.round((float)(particles_list.get(i)[0].get_x())); 
            int w_w = Math.round((float)(particles_list.get(i)[0].get_width() * s)); 
            int w_h = Math.round((float)(particles_list.get(i)[0].get_height() * s)); 
			
			
			int x0 = w_c - w_w / 2; 
			int y0 = w_r - w_h / 2;
			int x1 = w_w;
			int y1 = w_h;
			
			System.out.println("Text region : " + i + ", weight : " + particles_list.get(i)[0].get_weight() + ", flag : " + particles_list.get(i)[0].valid);
            	
			
			
			
			if ( ((w_c - w_w / 2 + w_w) > image.getWidth() || (w_r - w_h / 2 + w_h) > image.getHeight() || (w_c - w_w / 2) < 0 || (w_r - w_h / 2) < 0)) {
            	/*Remove all elements that have coordinates outside the image frame*/
				/*BufferedImage iBox = image.getSubimage(x0, y0, x1, y1);
				
				try {
					ImageIO.write(iBox, "png", new File(io_parameters.get_out_path() + String.format("%05d", iframe) + "/perdi_" + E.get_label()  + ".png"));
				}
				catch (Exception e) {
					e.printStackTrace();
					System.exit(1);
				}*/
				
				//set_T.remove(i);
				remove[i] = true;
				System.out.printf("Ooops saiu : %d %d %d %d - w : %d, h : %d\n", x0, y0, x1, y1, x0+y0, x1+y1); 

      	    }
			/*else if ( !particles_list.get(i)[0].valid) {
				 
				 //set_T.remove(i);
				 System.out.printf("Ooops valid false : %d %d %d %d - w : %d, h : %d\n", x0, y0, x1, y1, x0+y0, x1+y1); 
				 particles P = new particles();
				 P.display_particle3(tmp, particles_list.get(i)[0], i, E.get_label());
				 remove[i] = true;	
			 }
			else if ( E.get_fp() >= 5) {
				 
				 //set_T.remove(i);
				 System.out.printf("Ooops 3 vezes ruim: %d %d %d %d - w : %d, h : %d\n", x0, y0, x1, y1, x0+y0, x1+y1); 
				 particles P = new particles();
				 P.display_particle4(tmp, particles_list.get(i)[0], i, E.get_label());
				 remove[i] = true;	
			 }*/
      	  else {
      		  

			
			/*if ((x0 + x1) > image.getWidth()) {
				x1 = image.getWidth() - x0 -1;
			}
			if ((y0 + y1) > image.getHeight()) {
				y1 = image.getHeight() - y0 -1;
			}*/

			//if ( (x0 >= 0) && (y0 >= 0) &&  ( (x0 + x1) < image.getWidth() ) && ( (y0 + y1) < image.getHeight() )  ) {

	
                BufferedImage iBox = image.getSubimage(w_c - w_w / 2, w_r - w_h / 2, w_w, w_h);
				//BufferedImage iBox = image.getSubimage(x0, y0, x1, y1);
				
				
						
				try {
					ImageIO.write(iBox, "png", new File(io_parameters.get_out_path() + String.format("%05d", iframe) + "/box_" + E.get_label()  + ".png"));
				}
				catch (Exception e) {
					e.printStackTrace();
					System.exit(1);
				}

				double v =  HoG_Functions.Get_HoG_Score (iBox, hogmean, hogstd, cls, detection_parameters); 

				particles P = new particles();

				/*VERIFICAR ISSO ?????????????*/
				if (v >= 0) {
					//textzones tz = tzones.get(k);
					/*for (int j = 1; j < tracking_parameters.number_of_particles; j++) {
						P.display_particle2(tmp, particles_list.get(i)[j], i, E.get_label());
					}*/
					P.display_particle(tmp, particles_list.get(i)[0], i, E.get_label());
					//P.display_particle(image, particles_list.get(i)[0], i, E.get_label());
				}
				else {
					P.display_particle(tmp, particles_list.get(i)[0], i, E.get_label());
					/*for (int j = 1; j < number_of_particles; j++) {
						P.display_particle2(image, particles_list.get(i)[j], i, E.get_label());
					}*/
					//textzones tz = tzones.get(k);
					//P.display_particle2(image, particles_list.get(i)[0], i, E.get_label());
				}

				/*if ( (E.get_weight() != -Double.MIN_VALUE) && (detection) ) {
					ft = (1.0 - tracking_parameters.rho)*E.get_weight() + (tracking_parameters.rho * v);	
					System.out.printf("Case 1 - caixa : %d, hog_weight : %f, ft : %f\n", i, v, ft);
				}
				else if (detection) {
					ft = (1.0 - tracking_parameters.rho)*v  + (tracking_parameters.rho * v);
					System.out.printf("Case 2 - caixa : %d, hog_weight : %f, ft : %f\n", i, v, ft);
				}
				else {
					System.out.printf("Before: tracking_parameters.rho %f, diff : %f, r1 : %f, r2 : %f\n", tracking_parameters.rho, 1.0 - tracking_parameters.rho, (1.0 - tracking_parameters.rho)*ft, tracking_parameters.rho * v);
					ft = (1.0 - tracking_parameters.rho)*ft + (tracking_parameters.rho * v);
					System.out.printf("After Case 3 - caixa : %d, hog_weight : %f, ft : %f\n", i, v, ft);
				}*/
				
				/*Newly detected region*/
				if (E.get_weight() == -Double.MIN_VALUE) {
					E.set_weight(v);
				}
				else {
					E.set_weight((1.0 - tracking_parameters.rho)*E.get_weight() + (tracking_parameters.rho * v));
				}
				
				//System.out.printf("caixa : %d, hog_weight : %f, ft : %f\n", i, v, E.get_weight());
			

			//if (frame == eframe) {

			//textzones tz = tzones.get(k);
			E.set_x(x0);
			E.set_y(y0);
			E.set_width(x1);
			E.set_height(y1);
			
			if (E.get_weight() < 0.0) {
				E.set_fp(E.get_fp()+1);
			}
			else {
				E.set_fp(0);
			}
			//E.set_weight(ft); 

			//DIFERENCA ENTRE TEMPLATE FIXO OU VARIAVEL
			//if (detection) {	//-> MUITO CUIDADO AVALIAR ESSE COMANDO E POSICAO	
				if (x0 > 0 && y0 > 0 && (x0+x1) < image.getWidth() && (y0+y1) < image.getHeight()) {
					E.image = image.getSubimage(x0, y0, x1, y1);
					
					try {
						ImageIO.write(E.image, "png", new File(io_parameters.get_out_path() + String.format("%05d", iframe) + "/comparada_" + E.get_label()  + ".png"));
					}
					catch (Exception e) {
						e.printStackTrace();
						System.exit(1);
					}
				}

			//}
				
			}
			//else {
				/*Remove all elements that have coordinates outside the image frame*/
				/*BufferedImage iBox = image.getSubimage(x0, y0, x1, y1);
				
				try {
					ImageIO.write(iBox, "png", new File(io_parameters.get_out_path() + String.format("%05d", iframe) + "/perdi_" + E.get_label()  + ".png"));
				}
				catch (Exception e) {
					e.printStackTrace();
					System.exit(1);
				}*/
				
				//set_T.remove(i);
				//System.out.printf("Ooops saiu : %d %d %d %d - w : %d, h : %d\n", x0, y0, x1, y1, x0+y0, x1+y1); 
				
				
			//}

		}
		
		//System.out.printf("No final \n");

		Icdar.toXML (String.format("%06d", iframe) + ".xml",  io_parameters.get_out_path() + String.format("%05d", iframe) + "/out.tracked.xml", image.getWidth(), image.getHeight(), set_T, detection_parameters); 

		try {
			ImageIO.write(tmp, "png", new File(io_parameters.get_out_path() + String.format("%05d", iframe) + "/tracking.png"));
			ImageIO.write(image, "png", new File(io_parameters.get_out_path() + String.format("%05d", iframe) + "/originar.png"));
		}
		catch (Exception e) {
			e.printStackTrace();
			System.exit(1);
		}
			
		long stop = System.currentTimeMillis(); 
		//System.out.println("Tracking (time - seconds): " + (stop-start)); 
		
		/*for (int i = 0; i < set_T.size(); i++) { 
			if (remove[i]) {
				set_T.remove(i);
				particles_list.remove(i);
			}
		}*/ 
		
		return particles_list;
	}
	
	static ArrayList<particle[]> PF ( 
			int iframe,
			BufferedImage image,
			ArrayList<Atributes> set_T,
			ArrayList<particle[]> particles_list,
			boolean added,
			String sout_path,
			tracking_arguments tracking_parameters) 
			throws FileNotFoundException, ClassNotFoundException, IOException  
	{

		BufferedImage tmp = Util.imageScale (image, 1.0);
		
		//BufferedImage tmp = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_ARGB);
		
		ArrayList<String> hog_parameters = HoG_Functions.get_hog_parameters (tracking_parameters.hog_parameters_trained);
				
		SMOSVM<double[]> cls = null;
		try {
			ObjectInputStream obj = new ObjectInputStream(new FileInputStream(tracking_parameters.hog_obj));
			cls = (SMOSVM<double[]>) obj.readObject();
			obj.close();
		}
		catch (Exception e){
			e.printStackTrace();
		}

		long start = System.currentTimeMillis();

		pfTracking pf = new pfTracking();

		if (added) {
			particles_list.clear();
			particles_list = new ArrayList<particle[]>();			
			for (int i = 0; i < set_T.size(); i++) {
				Atributes E = set_T.get(i);
				pf.Initialization(E.image, (int)(E.get_x()), (int)(E.get_y()), E.get_width(), E.get_height(), particles_list, i, tracking_parameters);
			}
		}		
		pf.Tracking (image, particles_list, particles_list.size(), iframe, tracking_parameters);
		
		long stop = System.currentTimeMillis(); 
		seconds += ((stop-start)/(double)1000.0);
		
		System.out.println("Tracking (time - seconds): " + ((stop-start)/(double)1000.0) + " , frame : " + iframe);
		
		
		boolean[] remove = new boolean[set_T.size()];

		for (int i = 0; i < set_T.size(); i++) { remove[i] = false; } 

		//Util.addTransparency (image, tmp);
		for (int i = 0; i < set_T.size(); i++) {

			Atributes E = set_T.get(i);

			double s = particles_list.get(i)[0].get_s();
			int w_r = Math.round((float)(particles_list.get(i)[0].get_y())); 
			int w_c = Math.round((float)(particles_list.get(i)[0].get_x())); 
			int w_w = Math.round((float)(particles_list.get(i)[0].get_width() * s)); 
			int w_h = Math.round((float)(particles_list.get(i)[0].get_height() * s)); 			
			int x0 = w_c - w_w / 2; int y0 = w_r - w_h / 2; int x1 = w_w; int y1 = w_h;

			if (  (w_c - w_w / 2 + w_w) > image.getWidth()  || (w_c - w_w / 2) < 0 ||
				  (w_r - w_h / 2 + w_h) > image.getHeight() || (w_r - w_h / 2) < 0 ) {
				/*Remove all elements that have coordinates outside the image frame*/
				remove[i] = true;
			}
			else {
				
				BufferedImage text_image = image.getSubimage(w_c - w_w / 2, w_r - w_h / 2, w_w, w_h);

				/*try {
					ImageIO.write(text_image, "png", new File(sout_path + String.format("%06d", iframe) + "/box_" + E.get_label()  + ".png"));
				}
				catch (Exception e) {
					e.printStackTrace();
				}*/
								
				particles P = new particles();
				
				/*for (int j = 1; j < tracking_parameters.number_of_particles; j++) {
				    P.display_particle2(tmp, particles_list.get(i)[j], i, E.get_label());
			    }*/
				P.display_particle(tmp, particles_list.get(i)[0], i, E.get_label());

				//if (tracking_parameters.similarity_option.equals("VALIDATION")) {
					double score = HoG_Functions.score (text_image, cls, hog_parameters);
					//System.out.printf("%d %f %f\n", iframe, score, particles_list.get(i)[0].get_weight());
				//}
					
				System.out.printf("%d %f %f %f\n", iframe, score, particles_list.get(i)[0].get_weight(), E.get_weight());
					
				if (E.get_weight() == -Double.MIN_VALUE) {
					E.set_weight(score);
				}
				else {
					E.set_weight((1.0 - tracking_parameters.rho)*E.get_weight() + (tracking_parameters.rho * score));
				}

				
				/*Updating text-object coordinates*/
				E.set_x(x0);
				E.set_y(y0);
				E.set_width(x1);
				E.set_height(y1);
				//E.image = image.getSubimage(w_c - w_w / 2, w_r - w_h / 2, w_w, w_h);
								
				if (E.get_weight() < 0.0) {
					E.set_fp(E.get_fp()+1);
					//if (E.get_fp() >=  4) {
					if (E.get_fp() >= 5) {
						set_T.remove(i);
						particles_list.remove(i);
						i--;
						System.out.printf("removing text (score svm negative 4 frames consecutives) : %d\n", iframe);
					}
				}
				else {
					E.set_fp(0);
				}
			}
		}

		Icdar.toXML (String.format("%06d", iframe),  sout_path + String.format("%06d", iframe) + "/tracked.xml", image.getWidth(), image.getHeight(), set_T); 

		try {
			ImageIO.write(tmp, "png", new File(sout_path + String.format("%06d", iframe) + "/tracking.png"));
			//ImageIO.write(image, "png", new File(sout_path + String.format("%06d", iframe) + "/originar.png"));
		}
		catch (Exception e) {
			e.printStackTrace();
			System.exit(1);
		}		
		return particles_list;
	}	
	
	
	static void write_set_regions (BufferedImage original, ArrayList<Atributes> set, io_arguments io_parameters, boolean option, int frame) {
		
		BufferedImage image = Util.imageScale (original, 1.0);
		
		for (int i = 0; i < set.size(); i++) {
			
			Graphics2D g = image.createGraphics();
			
	    	g.setStroke(new BasicStroke(2.0f));
	    	
		    g.setColor(Color.yellow);
			
			Atributes A = set.get (i);
			
			int x = (int)(A.get_x()); 
		    int y = (int)(A.get_y());
		    int w = A.get_width(); 
		    int h = A.get_height();
		    
		    g.drawRect(x, y, w, h);
	    	    	
	    	g.dispose();
		}
		try {
			if (option) {
				ImageIO.write(image, "png", new File(io_parameters.get_out_image() + ".list.png"));
			}
			else {
				ImageIO.write(image, "png", new File(io_parameters.get_out_path() + String.format("%06d", frame) + "/detection.png"));
			}
		}
		catch (Exception e) {
			if (option) {
				System.err.printf("cannot write image %s\n", io_parameters.get_out_image());
			}
			else {
				System.err.printf("cannot write image %s\n", io_parameters.get_out_path() + String.format("%06d", frame) + "/detection.png");
			}
		} 
		
	}

}
