void despertarTrack( tlcde* framesBuf, tlcde* lsTracks, tlcde* lsIds ){


	STFrame* frameData1;
	STTrack* NewTrack;
	STTrack* SleepingTrack;

	float distancia;	// almacena la distancia entre el track nuevo y los que duermen.
	float menorDistancia = 100000; // almacena el valor de la menor distancia
	int masCercano; // almacena la posición de la lista del track nuevo más cercano al track durmiendo
	float direccion;
	int a; // para hayar la distancia
	int b; // idem
	int tiempoVivo;

	if( framesBuf->numeroDeElementos < 3 ) return;
	frameData1 = (STFrame*)obtener(framesBuf->numeroDeElementos-1, framesBuf);
//	frameData0 = (STFrame*)obtener(0, framesBuf);
	if( lsTracks->numeroDeElementos <= trackParams->MaxBlobs  ) return;
	for(int i = 0;i < lsTracks->numeroDeElementos ; i++){
		// obtener Track
		NewTrack = (STTrack*)obtener(i, lsTracks);
		// comprobar si se han iniciado nuevos tracks. Los tracks que lleguen aqui
		// son posibles tracks válidos( no han sido eliminados en validar tracks), es decir,
		// llevan vivos 1 frames y tienen asignación válida
		tiempoVivo = frameData1->num_frame - NewTrack->Stats->InitTime ;
		if( tiempoVivo == 1 ){ //deteccion de nuevos tracks posiblemente válidos
			for(int j = 0;j < lsTracks->numeroDeElementos ; j++){
				// si hay tracks durmiendo escogemos el nuevo track más cercano con un umbral
				SleepingTrack = (STTrack*)obtener(j, lsTracks);
				if( SleepingTrack->Stats->Estado == SLEEPING  ){ // && SleepingTrack->id <= trackParams->MaxBlobs) ??si hay tracks durmiento
					// una vez se haya confirmado la validez de los tracks restringimos mas.

					// nos quedamos con el más cercano al punto donde se inicio el nuevo track
					a = NewTrack->Stats->InitPos.x - SleepingTrack->x_k_Pos->data.fl[0];
					b = NewTrack->Stats->InitPos.y - SleepingTrack->x_k_Pos->data.fl[1];
					EUDistance( a,b,&direccion, &distancia);
					if( (distancia < menorDistancia) && (distancia <  (int)obtenerFilterParam( MAX_JUMP ) ) ){
						masCercano = j;
						menorDistancia = distancia;
					}
				}
			}
			//Si se cumple la condición reasignamos
			if ( menorDistancia <= (int)obtenerFilterParam( MAX_JUMP )){
				dejarId( NewTrack, lsIds );
				reasignarTracks( lsTracks, framesBuf,lsIds,i,masCercano, UPDATE_STATS );
				deadTrack( lsTracks, masCercano );
			}
		}
	}
}
void ordenarTracks( tlcde* lsTracks ){

	STTrack* Track1;
	STTrack* Track2;
	int permutacion = 1;

	while( permutacion){
		permutacion = 0;
		for( int i = 1; i < lsTracks->numeroDeElementos; i++){
			Track1 = (STTrack*)obtener(i-1, lsTracks);
			Track2 = (STTrack*)obtener(i, lsTracks);
			if( Track1->id > Track2->id   ){
				permutacion = 1;
				Track1 = (STTrack*)borrarEl(i-1, lsTracks); // borra el elemento i-1. Actual apunta al sig (i)
				insertar( (STTrack*)Track1,lsTracks); // se inserta el track 1 a continuación del actual(i)
			}
		}
	}
}
unsigned int sumFrame( tlcde* Flies ){

	STFly* flyOut = NULL;
	float sumatorio = 0;
	unsigned int sumUint;
	for(int i = 0; i< Flies->numeroDeElementos ; i++){
		flyOut = (STFly*)obtener(i,Flies);
		sumatorio = flyOut->VInst + sumatorio;
	}
	sumUint = ( unsigned int)cvRound(sumatorio);
	return sumUint;
}
void Restaurar(tlcde* lista, IplImage* Fg, IplImage* Origin, CvRect Roi,
		int elemento) {
	STFly* FlyData;
	FlyData = (STFly *) obtener(elemento, lista);
	FlyData->failSeg = true;
	// restaurar
	cvSetImageROI(Origin, Roi);
	cvSetImageROI(Fg, Roi);
	cvCopy(Origin, Fg);
	cvResetImageROI(Origin);
	cvResetImageROI(Fg);
}
Exemple #5
0
main() {		
	int i = 0;
	Elemento *llse = NULL;
	double *n = NULL, d = 0;

	printf("Introducir datos. Finalizar con eof.\n");
	printf("Valor double: ");
	
	while(scanf("%lf", &d)!= EOF) {	
		n = (double *)malloc(sizeof(double));
		if(!n)
			error();
		*n=d;
		anyadirAlPrincipio(n, &llse);
		printf("Valor double: ");
	}
	printf("\n");
	
	i = 0;
	n = (double *)obtener(i, llse);
	while(n != NULL){
		printf("%g \n", *n); // printf("%g \n", *n); por un formato variable de impresion de los numeros %lf por el double
		i++;
		n = (double *)obtener(i, llse);
	}
	printf("\n%d valores.\n", i);
	
	i=0;
	n=(double *)obtener(i, llse);
	while(n != NULL){
		free(n);
		i++;
		n = (double *)obtener(i, llse);
	}

	borrarTodos(&llse);
}
double CalcProbTotal(tlcde* Lista, SHModel* SH, ValParams* Params,
		STFly* FlyData) {

	double PX = 1;
	double Pxi = 0;

	for (int i = 0; i < Lista->numeroDeElementos; i++) {

		FlyData = (STFly *) obtener(i, Lista);
		CalcProbFly(SH, FlyData, Params);
		PX = PX * Pxi;
	}

	return PX;
}
/*!\brief Calcula la Pxi de cada una de las flies resultado de la segmentación. En función de ésta
 * decide sobre si se a finalizado, se segmentará de nuevo alguno de los blobs resultantes por ser
 * aun muy grandeo bien se descarta la segmentación por dar algún blob un área demasiado pequeña,
 * restaurando así el original.
 *
 * Si el blob es válido ( sin exceso ni defecto) se establece flag_seg true ( segmentado correctamente ). Si no
 * es válido por exceso se establece flag_seg a false y se devuelve 1 (exito): el blob con exceso será
 * segmentado de nuevo.
 * si no es válida por defecto, se establece flag_seg a false pero en este caso se devuelve un 0 (fallo). Se
 * restaura el blob original.
 *
 * si Exeso = 0  => segmentación correcta.
 * si Exceso = 1 => segmentación correcta pero aun hay exceso
 * si Exceso = -1 => fallo en segmentación. Uno de los blobs es demasiado pequeño.
 * @param TempSeg
 * @param SH
 * @param Params
 * @return 1 si éxito, 0 si fallo.
 */
int comprobarPxi(tlcde* TempSeg, SHModel* SH, ValParams* Params) {
	STFly* FlyData;
	int Exceso;
	for (int j = 0; j < TempSeg->numeroDeElementos; j++) {
		// Calcular Pxi del/los blob/s resultante/s
		FlyData = (STFly *) obtener(j, TempSeg);
		Exceso = CalcProbFly(SH, FlyData, Params);
		if (Exceso == 0)
			FlyData->flag_seg = true;
		else if (Exceso == 1)
			FlyData->flag_seg = false;
		else if (Exceso == -1)
			return 0; // algún elemento no es correca
	}
	return 1; // correcta. aquellos con flyseg = false serán segmentados de nuevo
}
void statsBloB(STFrame* frameDataOut ){

	STFly* fly = NULL;
	frameDataOut->Stats->TotalBlobs = frameDataOut->Flies->numeroDeElementos;
	for(int i = 0; i< frameDataOut->Stats->TotalBlobs ; i++){
		fly = (STFly*)obtener(i,frameDataOut->Flies);
		if( fly->Estado == 1 ) frameDataOut->Stats->dinamicBlobs +=1;
		else frameDataOut->Stats->staticBlobs +=1;

		// velocidad instantánea
//		EUDistance( fly->Vx, fly->Vy, NULL, &fly->Stats->VInst);
	}
	frameDataOut->Stats->dinamicBlobs = (frameDataOut->Stats->dinamicBlobs/frameDataOut->Stats->TotalBlobs)*100;
	frameDataOut->Stats->staticBlobs = (frameDataOut->Stats->staticBlobs/ frameDataOut->Stats->TotalBlobs)*100;



}
void cleanGhosts( IplImage* FG, tlcde* flies ){

	STFly* flyData = NULL;
	cvCreateTrackbar( "Umbral borde plato","Foreground", &valParams->umbralCleanGhosts, 100, onTrackBarClean);
	int Ghost;
	if( !flies||flies->numeroDeElementos == 0) return;
	for (int i = 0; i < flies->numeroDeElementos; i++) {
		// Almacenar la Roi del blob visitado antes de ser validado
		flyData = (STFly *) obtener(i, flies);
		Ghost = verificarBlob(FG, flyData );
		// si es un reflejo, eliminar
		if( Ghost ){
			if (flyData->Tracks ) free(flyData->Tracks);
			if (flyData->Stats) free(flyData->Stats);
		    free(flyData); // borrar el área de datos del elemento eliminado
		    flyData = NULL;
		    flyData = (STFly *)borrarEl(i,flies);
		    i--;
		}
	}

}
void mediaMovil(  STStatsCoef* Coef, tlcde* vector, STStatFrame* Stats ){

	valorSum* valor;
	valorSum* valorT;

	// Se suma el nuevo valor
	valorT = ( valorSum*)obtener( vectorSumFr->numeroDeElementos-1 , vectorSumFr );
	Coef->F1SSum = Coef->F1SSum + valorT->sum;
	Coef->F1SSum2 = Coef->F1SSum2 + valorT->sum*valorT->sum;

	Coef->F30SSum = Coef->F30SSum + valorT->sum;
	Coef->F30SSum2 = Coef->F30SSum2 + valorT->sum*valorT->sum;

	Coef->F1Sum = Coef->F1Sum + valorT->sum;
	Coef->F1Sum2 = Coef->F1Sum + valorT->sum*valorT->sum;

	Coef->F5Sum = Coef->F5Sum + valorT->sum;
	Coef->F5Sum2 = Coef->F5Sum2 + valorT->sum*valorT->sum;

	Coef->F10Sum = Coef->F10Sum + valorT->sum;
	Coef->F10Sum2 = Coef->F10Sum2 +valorT->sum*valorT->sum;

	Coef->F30Sum = Coef->F30Sum + valorT->sum;
	Coef->F30Sum2 = Coef->F30Sum2 + valorT->sum*valorT->sum;

	Coef->F1HSum = Coef->F1HSum + valorT->sum;
	Coef->F1HSum2 = Coef->F1HSum2 + valorT->sum*valorT->sum;

	Coef->F2HSum = Coef->F2HSum + valorT->sum;
	Coef->F2HSum2 = Coef->F2HSum2 + valorT->sum*valorT->sum;

	Coef->F4HSum = Coef->F4HSum + valorT->sum;
	Coef->F4HSum2 = Coef->F4HSum2 + valorT->sum*valorT->sum;

	Coef->F8HSum = Coef->F48HSum + valorT->sum;
	Coef->F8HSum2 = Coef->F48HSum2 + valorT->sum*valorT->sum;

	if((unsigned)vector->numeroDeElementos > Coef->F1S){
	// los que hayan alcanzado el valor máximo restamos al sumatorio el primer valor
		valor = ( valorSum*)obtener( vectorSumFr->numeroDeElementos-1 - Coef->F1S, vectorSumFr );
		Coef->F1SSum = Coef->F1SSum - valor->sum; // sumatorio para la media
		Coef->F1SSum2 = Coef->F1SSum2 - (valor->sum*valor->sum);  // sumatorio para la varianza
		Stats->CMov1SMed   =  Coef->F1SSum / Coef->F1S; // cálculo de la media
		Stats->CMov1SDes  =  sqrt( abs(Coef->F1SSum2 / Coef->F1S - Stats->CMov1SMed*Stats->CMov1SMed ) ); // cálculo de la desviación
	}
	if(vector->numeroDeElementos > Coef->F30S){
		valor = ( valorSum*)obtener( vectorSumFr->numeroDeElementos-1 - Coef->F30S, vectorSumFr );
		Coef->F30SSum = Coef->F30SSum - valor->sum; // sumatorio para la media
		Coef->F30SSum2 = Coef->F30SSum2 - (valor->sum*valor->sum);  // sumatorio para la varianza
		Stats->CMov30SMed  =  Coef->F30SSum / Coef->F30S;
		Stats->CMov30SDes  =  sqrt( abs(Coef->F30SSum2 / Coef->F30S - Stats->CMov30SMed*Stats->CMov30SMed ));
	}
	if(vector->numeroDeElementos > Coef->F1){
		valor = ( valorSum*)obtener( vectorSumFr->numeroDeElementos-1 - Coef->F1, vectorSumFr );
		Coef->F1Sum = Coef->F1Sum - valor->sum;
		Coef->F1Sum2 = Coef->F1Sum2 - (valor->sum*valor->sum);
		Stats->CMov1Med    =  Coef->F1Sum / Coef->F1;
		Stats->CMov1Des    =  sqrt( abs(Coef->F1Sum2 / Coef->F1 -  Stats->CMov1Med *Stats->CMov1Med )) ;
	}
	if(vector->numeroDeElementos > Coef->F5){
		valor = ( valorSum*)obtener( vectorSumFr->numeroDeElementos-1 - Coef->F5, vectorSumFr );
		Coef->F5Sum = Coef->F5Sum - valor->sum;
		Coef->F5Sum2 = Coef->F5Sum2 - (valor->sum*valor->sum);
		Stats->CMov5Med    =  Coef->F5Sum / Coef->F5;
		Stats->CMov5Des    =  sqrt( abs(Coef->F5Sum2 / Coef->F5 - Stats->CMov5Med *Stats->CMov5Med ));
	}
	if(vector->numeroDeElementos > Coef->F10){
		valor = ( valorSum*)obtener( vectorSumFr->numeroDeElementos-1 - Coef->F10, vectorSumFr );
		Coef->F10Sum = Coef->F10Sum - valor->sum;
		Coef->F10Sum2 = Coef->F10Sum2 - (valor->sum*valor->sum);
		Stats->CMov10Med   =  Coef->F10Sum / Coef->F10;
		Stats->CMov10Des   =  sqrt( abs(Coef->F10Sum2 / Coef->F10 - Stats->CMov10Med*Stats->CMov10Med));
	}
	if(vector->numeroDeElementos > Coef->F15){
		valor = ( valorSum*)obtener( vectorSumFr->numeroDeElementos-1 - Coef->F15, vectorSumFr );
		Coef->F15Sum = Coef->F15Sum - valor->sum;
		Coef->F15Sum2 = Coef->F15Sum2 - (valor->sum*valor->sum);
		Stats->CMov15Med   =  Coef->F15Sum / Coef->F15;
		Stats->CMov15Des   =  sqrt( abs(Coef->F15Sum2 / Coef->F15 - Stats->CMov15Med*Stats->CMov15Med));
	}
	if(vector->numeroDeElementos > Coef->F30){
		valor = ( valorSum*)obtener( vectorSumFr->numeroDeElementos-1 - Coef->F30, vectorSumFr );
		Coef->F30Sum = Coef->F30Sum - valor->sum;
		Coef->F30Sum2 = Coef->F30Sum2- (valor->sum*valor->sum);
		Stats->CMov30Med   =  Coef->F30Sum / Coef->F30;
		Stats->CMov30Des   =  sqrt( abs(Coef->F30Sum2 / Coef->F30 - Stats->CMov30Med*Stats->CMov30Med));
	}
	if(vector->numeroDeElementos > Coef->F1H){
		valor = ( valorSum*)obtener( vectorSumFr->numeroDeElementos-1 - Coef->F1H, vectorSumFr );
		Coef->F1HSum = Coef->F1HSum - valor->sum;
		Coef->F1HSum2 = Coef->F1HSum2 - (valor->sum*valor->sum);
		Stats->CMov1HMed   =  Coef->F1HSum / Coef->F1H;
		Stats->CMov1HDes   =  sqrt( abs(Coef->F1HSum2 / Coef->F1H - Stats->CMov1HMed*Stats->CMov1HMed));
	}
	if(vector->numeroDeElementos > Coef->F2H){
		valor = ( valorSum*)obtener( vectorSumFr->numeroDeElementos-1 - Coef->F2H, vectorSumFr );
		Coef->F2HSum = Coef->F2HSum - valor->sum;
		Coef->F2HSum2 = Coef->F2HSum2 - (valor->sum*valor->sum);
		Stats->CMov2HMed   =  Coef->F2HSum / Coef->F2H;
		Stats->CMov2HDes   =  sqrt( abs(Coef->F2HSum2 / Coef->F2H - Stats->CMov2HMed*Stats->CMov2HMed));
	}
	if(vector->numeroDeElementos > Coef->F4H){
		valor = ( valorSum*)obtener( vectorSumFr->numeroDeElementos-1 - Coef->F4H, vectorSumFr );
		Coef->F4HSum = Coef->F4HSum - valor->sum;
		Coef->F4HSum2 = Coef->F4HSum2- (valor->sum*valor->sum);
		Stats->CMov4HMed   =  Coef->F4HSum / Coef->F4H;
		Stats->CMov4HDes   =  sqrt( abs(Coef->F4HSum2 / Coef->F4H - Stats->CMov4HMed*Stats->CMov4HMed));
	}
	if(vector->numeroDeElementos > Coef->F8H){
		valor = ( valorSum*)obtener( vectorSumFr->numeroDeElementos-1 - Coef->F8H, vectorSumFr );
		Coef->F8HSum = Coef->F48HSum - valor->sum;
		Coef->F8HSum2 = Coef->F8HSum2 - (valor->sum*valor->sum);
		Stats->CMov8HMed   = Coef->F8HSum / Coef->F8H;
		Stats->CMov8HDes   =  sqrt( abs(Coef->F8HSum2 / Coef->F8H - Stats->CMov8HMed*Stats->CMov8HMed));
	}
	if(vector->numeroDeElementos > Coef->F16H){
		valor = ( valorSum*)obtener( vectorSumFr->numeroDeElementos-1 - Coef->F16H, vectorSumFr );
		Coef->F16HSum = Coef->F16HSum - valor->sum;
		Coef->F16HSum2 = Coef->F16HSum2 - (valor->sum*valor->sum);
		Stats->CMov16HMed   = Coef->F16HSum / Coef->F16H;
		Stats->CMov16HDes  =  sqrt( abs(Coef->F16HSum2 / Coef->F16H - Stats->CMov16HMed*Stats->CMov16HMed));
	}
	if(vector->numeroDeElementos > Coef->F24H){
		valor = ( valorSum*)obtener( vectorSumFr->numeroDeElementos-1 - Coef->F24H, vectorSumFr );
		Coef->F24HSum = Coef->F24HSum - valor->sum;
		Coef->F24HSum2 = Coef->F24HSum2 - (valor->sum*valor->sum);
		Stats->CMov24HMed   = Coef->F24HSum / Coef->F24H;
		Stats->CMov24HDes  =  sqrt( abs(Coef->F24HSum2 / Coef->F24H - Stats->CMov24HMed*Stats->CMov24HMed));
	}
	if(vector->numeroDeElementos > Coef->F48H){
		valor = ( valorSum*)obtener( vectorSumFr->numeroDeElementos-1 - Coef->F48H, vectorSumFr );
		Coef->F48HSum = Coef->F48HSum - valor->sum;
		Coef->F48HSum2 = Coef->F48HSum2 - (valor->sum*valor->sum);
		Stats->CMov48HMed   = Coef->F48HSum / Coef->F48H;
		Stats->CMov48HDes  =  sqrt( abs(Coef->F48HSum2 / Coef->F48H - Stats->CMov48HMed*Stats->CMov48HMed));
	}

}
void Validacion2(IplImage *Imagen, STFrame* FrameData, SHModel* SH,StaticBGModel* BGModel,
		IplImage* Mask) {

	//Inicializar estructura para almacenar los datos cada mosca
	STFly *FlyData = NULL;


	int Exceso;//Flag que indica si la Pxi minima no se alcanza por exceso o por defecto.
	double Circul; // Para almacenar la circularidad del blob actual

	double Besthres = 0;// el mejor de los umbrales perteneciente a la mejor probabilidad
	double BestPxi = 0; // la mejor probabilidad obtenida para cada mosca

	// Establecemos los parámetros de validación por defecto

	// establecer los umbrales de resta iniciales

	if (valParams->privateParams == NULL) {
		PrivateValParams(SH,BGModel, &valParams->privateParams);
	}

	// Establecemos parámetros para los umbrales en la resta de fondo por defecto
	ValBGParams->LOW_THRESHOLD = valParams->privateParams->LThInicio;
	ValBGParams->HIGHT_THRESHOLD = valParams->privateParams->HThInicio;
	if( SH->FlyAreaDes == 0){
		printf("hola");
	}

	// almacenar una copia del FG para restaurar el blob en caso de que falle la validación
	cvCopy(FrameData->FG, Mask);

	// Recorremos los blobs uno por uno y los validamos.
	// Bucle for desde el primero hasta el ultimo individuo de la Lista FrameData->Flie del frame actual.
	// Los blobs resultantes de la fisión se añaden al final para ser validados de nuevo
	if (SHOW_VALIDATION_DATA)
		mostrarFliesFrame(FrameData);
	for (int i = 0; i < FrameData->Flies->numeroDeElementos; i++) {

		// Almacenar la Roi del blob visitado antes de ser validado


		FlyData = (STFly *) obtener(i, FrameData->Flies);
		if (FlyData->flag_seg == true)
			continue; // si el blob ha sido validado y es correcto pasar al siguiente

		CvRect FlyDataRoi = FlyData->Roi;
		// Inicializar LOW_THRESHOLD y demas valores
		ValBGParams->LOW_THRESHOLD = valParams->privateParams->LThInicio;
		ValBGParams->HIGHT_THRESHOLD = valParams->privateParams->HThInicio;
		FlyData->bestTresh = ValBGParams->LOW_THRESHOLD;

		// calcular su circularidad
		Circul = CalcCircul(FlyData);

		// Comprobar si existe Exceso o Defecto de area, en caso de Exceso la probabilidad del blob es muy pequeña
		// y el blob puede corresponder a varios blobs que forman parte de una misma moscas o puede corresponder a
		// un espurio.
		Exceso = CalcProbFly(SH, FlyData, valParams); // Calcular la px de la mosca.
		BestPxi = FlyData->Px;
		STFly* MejorFly = FlyData;// = NULL;
		// comprobar si está dentro de los límites:

		//	Params->MaxLowTH = *ObtenerMaximo(Imagen, FrameData ,FlyData->Roi);

		// En caso de EXCESO de Area
		/* Incrementar paulatinamente el umbral de resta de fondo hasta
		 * que haya fisión o bien desaparzca el blob sin fisionarse o bien
		 * no se supere la pximin.
		 * - Si hay fisión:
		 * 		-si los blobs tienen una probabilidad mayor que la pximin fin segmentacion
		 * 		-si alguno de ellos tiene una probabilidad menor a la pximin, restaurar original y aplicar EM
		 * - Si no hay fisión: Si el blob desaparece antes de alcanzar la pximin o
		 *  bien alcanza la pximin, restablecer el tamaño original del blob para aplicar EM
		 *
		 */
		if (Exceso > 0) {
			//Inicializar estructura para almacenar la lista de los blobs divididos.
			tlcde* TempSeg = NULL;

			ValBGParams->LOW_THRESHOLD = valParams->privateParams->LThInicio;
			ValBGParams->HIGHT_THRESHOLD = valParams->privateParams->HThInicio;
			// sustituir por un for con el número máximo de iteraciones.
			int j = 0;
			while (1) {
				// primero probar con el umbral anterior. si el blob desaparece o no da un resutado satisfactorio
				// proceder desde el umbral predetermindado

				// Incrementar umbral
				ValBGParams->LOW_THRESHOLD += 1;
				j++;
				// Restar fondo
				BackgroundDifference(Imagen, FrameData->BGModel, NULL,
						FrameData->FG, ValBGParams, FlyDataRoi);
				//verMatrizIm(FrameData->FG, FlyDataRoi);
				// Segmentar
				TempSeg = segmentacion2(Imagen, FrameData->BGModel,
						FrameData->FG, FlyDataRoi, NULL);

				DraWWindow(FrameData->FG, NULL, NULL, SHOW_VALIDATION_IMAGES, COMPLETO );

				// Comprobar si se ha conseguido dividir el blob y verificar si el resultado es optimo

				// 1) El blob desaparece antes de alcanzar la pximin sin dividirse. Restauramos el blob y pasamos al siguiente elemento.
				if (TempSeg->numeroDeElementos < 1 || TempSeg == NULL) {
					RestaurarElMejor(FrameData->Flies, FrameData->FG, MejorFly,
							FlyDataRoi, i);
					DraWWindow(FrameData->FG, NULL, NULL, SHOW_VALIDATION_IMAGES,
							COMPLETO );
					// liberar lista
					liberarListaFlies(TempSeg);
					break;
				}

				// 2) mientras no haya fisión
				else if (TempSeg->numeroDeElementos == 1) {

					FlyData = (STFly *) obtener(0, TempSeg);
					Exceso = CalcProbFly(SH, FlyData, valParams);
					// no se rebasa la pximin.Almacenar la probabilidad mas alta y continuar
					if (Exceso > -1 && j < valParams->MaxIncLTHIters
							&& ValBGParams->LOW_THRESHOLD < valParams->MaxLowTH) {
						if (FlyData->Px >= BestPxi) {
							MejorFly = FlyData;
							BestPxi = FlyData->Px;
							Besthres = ValBGParams->LOW_THRESHOLD;
						}
						liberarListaFlies(TempSeg);
						free(TempSeg);
						TempSeg = NULL;

						continue;
					}
					// se ha rebasado la pxmin o bien se ha alcanzado el máximo de iteraciones o bien se ha llegado
					// al máximo valor permitido. Restaurar y pasar al siguiente
					else {
						RestaurarElMejor(FrameData->Flies, FrameData->FG,
								MejorFly, FlyDataRoi, i);
						//Restaurar(FrameData->Flies, FrameData->FG, Mask, FlyDataRoi, i);
						liberarListaFlies(TempSeg);
						DraWWindow(FrameData->FG, NULL, NULL, SHOW_VALIDATION_IMAGES,
								COMPLETO );

						break;
					}
				}
				// 3) Hay fisión
				else if (TempSeg->numeroDeElementos > 1) {
					// comprobar si las pxi son válidas. En caso de que todas lo sean eliminar de la lista el blob segmentado
					// y añadirlas a la lista al final.
					int exito = comprobarPxi(TempSeg, SH, valParams);
					if (exito) {
						borrarEl(i, FrameData->Flies); // se borra el elemento dividido
						for (int j = 0; j < TempSeg->numeroDeElementos; j++) { // se añaden los nuevos al final
							FlyData = (STFly *) obtener(j, TempSeg);
							anyadirAlFinal(FlyData, FrameData->Flies);
						}

						if (SHOW_VALIDATION_DATA){
							printf("\n Lista Flies tras FISION\n");
							mostrarFliesFrame(FrameData);
						}
						i--; // decrementar i para no saltarnos un elemento de la lista

						break; // salir del while
					}
					// Se ha rebasado la pximin en alguno de los blobs resultantes. Restauramos y pasamos al sig. blob
					else {
						liberarListaFlies(TempSeg);
						Restaurar(FrameData->Flies, FrameData->FG, Mask,
								FlyDataRoi, i);

						break; // salir del while
					}
				}
			}// Fin del While
			//liberarListaFlies( TempSeg );
			if (TempSeg)
				free(TempSeg);
			TempSeg = NULL;
		} //Fin Exceso

		/* En el caso de DEFECTO disminuir el umbral, para maximizar la probabilidad del blob
		 * Si no es posible se elimina (spurio)
		 */

		else if (Exceso < 0) {

			STFly* MejorFly = NULL;
			CvRect newRoi;
			tlcde* TempSeg = NULL;

			ValBGParams->LOW_THRESHOLD = valParams->privateParams->LThInicio;
			ValBGParams->HIGHT_THRESHOLD = valParams->privateParams->HThInicio;

			newRoi = FlyDataRoi;
			BestPxi = 0;
			int j = 0;
			while (j < valParams->MaxDecLTHIters) {
				newRoi.height += 1;
				newRoi.width += 1;
				newRoi.x -= 1;
				newRoi.y -= 1;
				ValBGParams->LOW_THRESHOLD -= 1;
				if (ValBGParams->LOW_THRESHOLD == valParams->MinLowTH) {
					Restaurar(FrameData->Flies, FrameData->FG, Mask,
							FlyDataRoi, i);
					break;
				}

				//while(Exceso < 0 && ValBGParams->LOW_THRESHOLD > Params->MinLowTH && Params->MaxDecLTHIters){

				// Restar fondo
				BackgroundDifference(Imagen, FrameData->BGModel,
						FrameData->IDesvf, FrameData->FG, ValBGParams, newRoi);

				// Segmentar
				TempSeg = segmentacion2(Imagen, FrameData->BGModel,
						FrameData->FG, newRoi, NULL);
				//TempSeg = segmentacion(Imagen, FrameData, newRoi,NULL);
				DraWWindow(FrameData->FG, NULL, NULL, SHOW_VALIDATION_IMAGES, COMPLETO );

				if (TempSeg == NULL || TempSeg->numeroDeElementos < 1)
					continue;
				// Calcular la pxi
				FlyData = (STFly *) obtener(0, TempSeg);
				Exceso = CalcProbFly(SH, FlyData, valParams); // Calcular la px de la mosca.

				// mientras la probabilidad se incremente continuamos decrementando el umbral
				j++;
				if (FlyData->Px >= BestPxi) {
					MejorFly = (STFly *) obtener(0, TempSeg);
					BestPxi = FlyData->Px;
					Besthres = ValBGParams->LOW_THRESHOLD;
				} else if (FlyData->Px < BestPxi || j
						== valParams->MaxDecLTHIters) {
					// cuando deje de mejorar o bien se llegue al máximo de iteraciones
					//nos quedamos con aquel que dio la mejor probabilidad. Lo insertamos en la lista en la misma posición.
					DraWWindow(FrameData->FG, NULL, NULL, SHOW_VALIDATION_IMAGES,
							COMPLETO );
					sustituirEl(MejorFly, FrameData->Flies, i);
					break;
				}
				liberarListaFlies(TempSeg);
				if (TempSeg) {
					free(TempSeg);
					TempSeg = NULL;
				}

			}// FIN WHILE
			liberarListaFlies(TempSeg);
			if (TempSeg)
				free(TempSeg);

		}// FIN DEFECTO

	}//FOR
	dibujarBGFG( FrameData->Flies,FrameData->FG,1);
	if (valParams->CleanGhosts){
		cleanGhosts(FrameData->FG, FrameData->Flies);
		dibujarBGFG( FrameData->Flies,FrameData->FG,1);
		cvAdd( FrameData->FG, maskCleanGhost, FrameData->FG);
	}


}//Fin de Validación
Exemple #12
0
void menu(matriz A, matriz B)
{int op; limpiar();double x;
 gotoxy(10,5);  cout<<"[1] OBTENER UN ELEMENTO DE A..";
 gotoxy(10,6);  cout<<"[2] OBTENER UN ELEMENTO DE B..";
 gotoxy(10,7);  cout<<"[3] ASIGNAR UN ELEMENTO DE A..";
 gotoxy(10,8);  cout<<"[4] ASIGNAR UN ELEMENTO DE B..";
 gotoxy(10,9);  cout<<"[5] IGUALAR A<-B..............";
 gotoxy(10,10); cout<<"[6] IGUALAR B<-A..............";
 gotoxy(10,11); cout<<"[7] SUMAR A + B...............";
 gotoxy(10,12); cout<<"[8] NEGATIVA DE A.............";
 gotoxy(10,13); cout<<"[9] NEGATIVA DE B.............";
 gotoxy(10,14); cout<<"[10] RESTAR A - B.............";
 gotoxy(10,15); cout<<"[11] RESTAR B - A.............";
 gotoxy(10,16); cout<<"[12] ESCALAR PARA A...........";
 gotoxy(10,17); cout<<"[13] ESCALAR PARA B...........";
 gotoxy(10,18); cout<<"[14] PRODUCTO A * B...........";
 gotoxy(10,19); cout<<"[15] PRODUCTO B * A...........";
 gotoxy(10,20); cout<<"[16] TRANSPUESTA DE A.........";
 gotoxy(10,21); cout<<"[17] TRANSPUESTA DE B.........";
 gotoxy(10,22); cout<<"[18] DETERMINANTE DE A........";
 gotoxy(10,23); cout<<"[19] DETERMINANTE DE B........";
 gotoxy(10,24); cout<<"[20] INVERSA DE A.............";
 gotoxy(10,25); cout<<"[21] INVERSA DE B.............";
 gotoxy(10,26); cout<<"[22] SALIR....................";
 do{gotoxy(22,28); cout<<"Seleccione una opcion (1-22): ";cin>>op;
 if(op<1 || op>22)
  {gotoxy(20,28);cout<<"Opci¢n incorrecta vuelva a intentar";}
 }while(op<1 || op>22);
 switch(op)
 {case 1:  {limpiar();gotoxy(28,4);  cout<<"[1] OBTENER UN ELEMENTO DE A..";
	    obtener(A);menu(A,B);break;}
  case 2:  {limpiar(); gotoxy(28,4); cout<<"[2] OBTENER UN ELEMENTO DE B..";
	    obtener(B);menu(A,B);break;}
  case 3:  {limpiar(); gotoxy(28,4); cout<<"[3] ASIGNAR UN ELEMENTO DE A..";
	    imprimir(asignar(A));getchar();menu(A,B);break;}
  case 4:  {limpiar(); gotoxy(28,4); cout<<"[4] ASIGNAR UN ELEMENTO DE B..";
	    imprimir(asignar(B));getchar();menu(A,B);break;}
  case 5:  {limpiar(); gotoxy(28,4); cout<<"[5] IGUALAR A<-B..............";
	    imprimir(igual(A,B));menu(A,B);break;}
  case 6:  {limpiar(); gotoxy(28,4); cout<<"[6] IGUALAR B<-A..............";
	    imprimir(igual(B,A));menu(A,B);break;}
  case 7:  {limpiar(); gotoxy(28,4); cout<<"[7] SUMAR A + B...............";
	    imprimir(sumar(A,B));menu(A,B);break;}
  case 8:  {limpiar(); gotoxy(28,4); cout<<"[8] NEGATIVA DE A.............";
	    imprimir(negativa(A));menu(A,B);break;}
  case 9:  {limpiar(); gotoxy(28,4); cout<<"[9] NEGATIVA DE B.............";
	    imprimir(negativa(B));menu(A,B);break;}
  case 10: {limpiar(); gotoxy(28,4); cout<<"[10] RESTAR A - B.............";
	    imprimir(restar(A,B));menu(A,B);break;}
  case 11: {limpiar(); gotoxy(28,4); cout<<"[11] RESTAR B - A.............";
	    imprimir(restar(B,A));menu(A,B);break;}
  case 12: {limpiar(); gotoxy(28,4); cout<<"[12] ESCALAR PARA A...........";
	    imprimir(escalar(A));menu(A,B);break;}
  case 13: {limpiar(); gotoxy(28,4); cout<<"[13] ESCALAR PARA B...........";
	    imprimir(escalar(B));menu(A,B);break;}
  case 14: {limpiar(); gotoxy(28,4); cout<<"[14] PRODUCTO A * B...........";
	    imprimir(producto(A,B));menu(A,B);break;}
  case 15: {limpiar(); gotoxy(28,4); cout<<"[15] PRODUCTO B * A...........";
	    imprimir(producto(B,A));menu(A,B);break;}
  case 16: {limpiar(); gotoxy(28,4); cout<<"[16] TRANSPUESTA DE A.........";
	    imprimir(transpuesta(A));menu(A,B);break;}
  case 17: {limpiar(); gotoxy(28,4); cout<<"[17] TRANSPUESTA DE B.........";
	    imprimir(transpuesta(B));menu(A,B);break;}
  case 18: {limpiar(); gotoxy(28,4); cout<<"[18] DETERMINANTE DE A........";
	    x=det(A);gotoxy(5,5);cout<<"Determinante = "<<x;getchar();menu(A,B);break;}
  case 19: {limpiar(); gotoxy(28,4); cout<<"[19] DETERMINANTE DE B........";
	    x=det(B);gotoxy(5,5);cout<<"Determinante = "<<x;getchar();menu(A,B);break;}
  case 20: {limpiar(); gotoxy(28,4); cout<<"[20] INVERSA DE A.............";
	    inversa(A);menu(A,B);break;}
  case 21: {limpiar(); gotoxy(28,4); cout<<"[21] INVERSA DE B.............";
	    inversa(B);menu(A,B);break;}
  case 22: {limpiar(); gotoxy(28,4); cout<<"[22] SALIR....................";
	    gotoxy(10,10); cout<<"Saliendo...";
	    gotoxy(25,23); cout<<"Presione Enter Para Salir...";break;
	   }
 }
}
/*!\brief Si recibe track nuevo:
 * Sustituye el track antiguo por el nuevo, actualiza los datos del nuevo en base a los del antiguo.
 * si no hay trak nuevo:
 * Elimina todo rastro del track antiguo incluyendo el blob que rastreaba. Este caso es de tracks que seguian a blobs con una
 * alta probabilidad de ser falsos.
 *
 *
 *
 * @param lsTracks
 * @param nuevo
 * @param viejo
 * @param framesBuf
 */
void reasignarTracks( tlcde* lsTracks,tlcde* framesBuf, tlcde* lsIds , int nuevo, int viejo, int Accion ){

	// obtener posicion del buffer desde la que hay que corregir.
	STFrame* frameData1 = NULL;
	STTrack* NewTrack = NULL;
	STTrack* SleepingTrack = NULL;
	STFly* Fly = NULL;


	int posInit; // posición del buffer desde la que se inicia la correción

	// obtener Track//

	SleepingTrack = (STTrack*)obtener(viejo, lsTracks);
	if(Accion != BORRAR ) NewTrack= (STTrack*)obtener(nuevo, lsTracks);
	if(Accion == BORRAR || Accion == RE_ETIQUETAR){ // en caso de que no haya nuevo track,
		posInit = (framesBuf->numeroDeElementos-1) -  SleepingTrack->Stats->FrameCount  ;
		if(posInit < 0) posInit = 0;
		// eliminamos del buffer los datos de su fly.
		if(Accion == RE_ETIQUETAR){
			SleepingTrack->id = NewTrack->id;
			SleepingTrack->Color = NewTrack->Color;
		}
		irAl( posInit,framesBuf);
		for( int i = posInit; i < framesBuf->numeroDeElementos; i++ ){
				// obtener frame
				frameData1 = (STFrame*)obtenerActual( framesBuf);
				//frameData1 = (STFrame*)obtener(i, framesBuf);
				irAlPrincipio( frameData1->Flies);
				for( int j = 0;j < frameData1->Flies->numeroDeElementos ; j++){
					Fly = (STFly*)obtenerActual( frameData1->Flies);
					if( Accion == BORRAR){
						// Limpiar datos del track indicado por la variable viejo y su blob
						if( Fly->etiqueta == SleepingTrack->id ){
							borrar(frameData1->Flies);
							if (Fly->Tracks ) free(Fly->Tracks);
							if (Fly->Stats) free(Fly->Stats);
							free(Fly); // borrar el área de datos del elemento eliminado
						}
					}// se etiquetan las flies con id del viejo con la id del nuevo. Se continuará con el viejo
					// re_etiquetado como el nuevo.
					else if( Accion == RE_ETIQUETAR){
						Fly = (STFly*)obtenerActual( frameData1->Flies);
						if( Fly->etiqueta == SleepingTrack->id ){
							Fly->etiqueta = NewTrack->id;
							Fly->Color =  NewTrack->Color;
						}
					}
					irAlSiguiente(frameData1->Flies );
				}
				irAlSiguiente( framesBuf);
		}

	}
	else{ // se actualiza el nuevo con los datos del antiguo y se continua con el nuevo
		// obtener posición desde la que se corrige la id.

		posInit = framesBuf->numeroDeElementos -  NewTrack->Stats->FrameCount ;
		// corregir buffer. No se eliminan los datos de la fly, sino que se actualizan
		if(posInit < 0) posInit = 0;
		// Usar la etiqueta, no fly sig, ya que sino se pisaría la etiqueta 0 ( KAM_CONTROL )
		for( int i = posInit; i < framesBuf->numeroDeElementos; i++ ){
			// obtener frame
			frameData1 = (STFrame*)obtener(i, framesBuf);
			for( int j = 0;j < frameData1->Flies->numeroDeElementos ; j++){
				Fly = (STFly*)obtener(j, frameData1->Flies);
				if( Fly->etiqueta == NewTrack->id ){
					if( Accion == ONLY_UPDATE_IDS){
						Fly->etiqueta = SleepingTrack->id;
						Fly->Color = SleepingTrack->Color;
					}
					else{
						Fly->etiqueta = SleepingTrack->id;
						Fly->Color = SleepingTrack->Color;
						Fly->dstTotal = SleepingTrack->Stats->dstTotal + Fly->dstTotal;
					}
				}
			}

		}
		// ACTUALIZAR TRACK
		if( Accion == ONLY_UPDATE_IDS){
			NewTrack->id = SleepingTrack->id;
			NewTrack->Color = SleepingTrack->Color;

		}else{
			NewTrack->id = SleepingTrack->id;
			NewTrack->Color = SleepingTrack->Color;
			NewTrack->Stats->dstTotal = SleepingTrack->Stats->dstTotal + NewTrack->Stats->dstTotal;
			NewTrack->Stats->FrameCount = SleepingTrack->Stats->FrameCount;
			NewTrack->Stats->InitTime = SleepingTrack->Stats->InitTime;
			NewTrack->Stats->InitPos = SleepingTrack->Stats->InitPos;
			NewTrack->Stats->TimeBlobOff = SleepingTrack->Stats->TimeBlobOff + NewTrack->Stats->TimeBlobOff;
			NewTrack->Stats->TimeBlobOn = SleepingTrack->Stats->TimeBlobOn + NewTrack->Stats->TimeBlobOn;

		}
	}
}
void corregirTracks( tlcde* framesBuf, tlcde* lsTracks, tlcde* lsIds){


	STFrame* frameData1;
	STTrack* NewTrack;
	STTrack* SleepingTrack;

	int masAntiguo ;
	int tiempoVivo;
	// posición (tiempo) desde el que se van a examinar nuevos tracks
	// si fuese 0 se pisaría a despertarTrack
	frameData1 = (STFrame*)obtener(framesBuf->numeroDeElementos-1, framesBuf);

//	irAlPrincipio( lsTracks);
	for(int i = 0;i < lsTracks->numeroDeElementos ; i++){
		// obtener Track// de los durmiendo, buscamos asignar en primer lugar el de etiqueta más baja.
		// damos prioridad a los menores o iguales a maxTrack, como están en orden, recorremos la lista
		// en orden

		SleepingTrack = (STTrack*)obtener(i, lsTracks);
//		if( SleepingTrack->Stats->Estado == SLEEPING &&
//						SleepingTrack->id <= trackParams->MaxBlobs &&
//						SleepingTrack->EstadoCount == MAX_BUFFER )

		if( SleepingTrack->Stats->Estado == SLEEPING &&
				SleepingTrack->Stats->EstadoCount >= (unsigned)trackParams->MaxBuffer-1 ){ //todo antes era ==
			// intentamos asignarle un nuevo track
			// damos prioridad a los que tengan la menor etiqueta frente a los más altos,
			// que es lo  mismo que escojer el nuevo track más antiguo
			int ultimo = 0;

			for( int j = 0;j < lsTracks->numeroDeElementos ; j++){
				// de los nuevos asignaremos el que lleve más tiempo vivo.
				NewTrack = (STTrack*)obtener(j, lsTracks);
				tiempoVivo = frameData1->num_frame - NewTrack->Stats->InitTime;
				if( tiempoVivo < trackParams->MaxBuffer && tiempoVivo > ultimo ){
					masAntiguo = j;
					ultimo = tiempoVivo;
				}
			}
			if( ultimo != 0){
				dejarId( NewTrack, lsIds );
				reasignarTracks( lsTracks, framesBuf,lsIds, masAntiguo , i, UPDATE_STATS );
				deadTrack( lsTracks, i );
				continue;
				// si se ha conseguido asignar continuar al siguiente
			}
			//. Si no es que no hay nuevos tracks. En este caso
			// si su etiqueta es menor que maxTracks, no hacer nada. Esperar a que aparezca el nuevo track.
			// Nunca será eliminado un track de este tipo. Se intentará reasignar al más adecuado en cuanto
			// sea posible
			if(	SleepingTrack->id <= trackParams->MaxBlobs ) continue;
			// en cambio si su etiqueta es mayor, si durante un tiempo no aparecen nuevos tracks, eliminarlo
			// , dejar su id y eliminar los datos de la fly que creó.
			else {
				dejarId( SleepingTrack, lsIds );
				reasignarTracks(lsTracks, framesBuf, lsIds, -1, i, BORRAR);
				deadTrack( lsTracks, i );
			}
		}

	}


}
int validarTracks(tlcde* framesBuf, tlcde* lsTracks, tlcde* identities, int MaxTracks, int numFrame ){

	STTrack* Track = NULL;
	STTrack* Track2 = NULL;

	int valCount = 0;

	// VALIDAR NUEVOS TRACKS

	// únicamente serán validos aquellos tracks que los primeros instantes tengan asignaciones válidas
	// y unicas. Si no es así será un trackDead originado por ruido:
	// Un track será válido cuando se verifique que es estable. Un track se considerará estable cuando
	// transcurran T frames sin pasar a estado KalmanControl desde su nacimiento. Si no es estable será
	// eliminado. Si se ha eliminado un track prioritario y existe un track de id mayor a max track
	// a dicho track se le asignará la id del track eliminado.

	if( lsTracks->numeroDeElementos < 1) return 0;
	irAlPrincipio( lsTracks);
	for(int i = 0;i < lsTracks->numeroDeElementos ; i++){
			// obtener Track
			Track = (STTrack*)obtenerActual( lsTracks);
			// eliminar los tracks creados en t y sin asignación en t+1
			if( falsoTrack( Track, numFrame ) ){
				dejarId( Track, identities );
				reasignarTracks(lsTracks, framesBuf, identities, -1, i, BORRAR );
				deadTrack( lsTracks, i );
			}
			// ELIMINAR TRACKS NO VERIFICADOS
			// Eliminar tracks con alta id que hayan nacido hace menos de max buffer frames y pasen a estado kalmanControl
			unsigned int tiempoVivo = numFrame - Track->Stats->InitTime ;
			// Eliminar tracks con alta id que hayan nacido hace menos de T frames y pasen a estado kalmanControl
			if( (tiempoVivo <= 200) &&(Track->Stats->Estado != CAM_CONTROL)){
				Track->validez = false;
			}
			else {
				Track->validez = true;
			}
			if( !Track->validez )
			 {
				// En los primeros MaxBuffer frames, si nos hemos cargado un track de los prioritarios
				// comprobar si hay tracks con id mayor a MaxTracks y reasignar el de mayor id y CamControl en caso afimativo
				if (framesBuf->numeroDeElementos< trackParams->MaxBuffer){
					irAlFinal(lsTracks);
					for(int j = lsTracks->numeroDeElementos - 1; j = 0 ; j--){
						unsigned int tiempoVivo = numFrame - Track->Stats->InitTime ;
						// si se encuentra un track en estado camControl de id mayor, se reasigna. El de mayor id
						// pasa a tomar la etiqueta del menor y se corrige el buffer,
						Track2 = (STTrack*)obtener( j,lsTracks);
						if( ( Track2->id > Track->id )&&(Track2->Stats->Estado == CAM_CONTROL)&&(Track2->Stats->EstadoCount == tiempoVivo )){
							dejarId( Track2, identities );
							reasignarTracks( lsTracks, framesBuf, identities, i , j, RE_ETIQUETAR );
							deadTrack(lsTracks, i );
							break;
						}
						else if(Track2->id == Track->id ){ // si no encuentra uno directamente se elimina
							dejarId( Track, identities );
							reasignarTracks(lsTracks, framesBuf, identities,-1, i, BORRAR );
							deadTrack(lsTracks, i );
						}
					}
				}
				// Si ya ha transcurrido el periodo inicial, Se elimina (si su id es mayor que maxBlobs ?? )
				else{
					if( Track->id > trackParams->MaxBlobs){

						dejarId( Track, identities );
						reasignarTracks(lsTracks, framesBuf, identities, -1, i, BORRAR);
						deadTrack( lsTracks, i );
					}
				}
				irAl( i-1, lsTracks);
			}

			irAlSiguiente( lsTracks);
	}//FIN FOR


	return valCount;

}
Exemple #16
0
void main(){
	//mostramos una imagen super fancy
	imprimeImagenPrincipal("        ");
	printf("\n\n\tPulsa [ENTER] para comenzar!\n");
	pausa();
	//srand(time(NULL));
	char opcion[STRING_MAX];
	char opcionJuego[STRING_MAX];
	boolean menu = TRUE; //variable del bucle del menu de opciones inicial
	boolean juego = FALSE; //variable del bucle del juego
	boolean buclePreJuego = FALSE; //variable del bucle de las opciones del juego
	boolean bucleTurnosJuego = FALSE; //variable del bucle de las jugadas

	//============================================
	// BUCLE MENU PRINCIPAL
	//--------------------------------------------
	while(menu){
		//limpia la consola
		limpiar();
		imprimeMenuPrincipal();
		fflush(stdin); //limpia buffer entrada
		fgets(opcion, STRING_MAX, stdin);

		//Opciones de entrada

		//opcion 1: entrar a un juego nuevo.
		if(atoi(opcion) == 1){
			buclePreJuego = TRUE;
		}
		//opcion 2: salir
		if(atoi(opcion) == 2){
			menu = FALSE;
		}

		//====================================================
		// BUCLE PRE-JUEGO
		//----------------------------------------------------
		
		char cantidadJugadores[STRING_MAX];
		nodo* jugadores = NULL; //jugadores
		nodo* mazo = NULL; //mazo del juego
		nodo* pozo = NULL; //donde se tiran las cartas
		nodo** manos = NULL; // cartas de los jugadores (puntero doble porque es un malloc de nodo*)

		while(buclePreJuego){
			//====================================================
			// CONDICIONES PRE-JUEGO
			//----------------------------------------------------
			limpiar();
			printf("Condiciones pre-juego.\n");
			
			//cuantos jugadores (incluyendo el humano)
			printf("ingrese la cantidad de jugadores [2-10]: ");
			fflush(stdin);
			fgets(cantidadJugadores,STRING_MAX, stdin);
			printf("jugadores: %d\n", atoi(cantidadJugadores));

			if(atoi(cantidadJugadores) < 2){
				buclePreJuego = FALSE;
			}
			else{
				//hacemos un arreglo de listas enlazadas que seran las manos.
				manos = (nodo**)malloc(sizeof(nodo*)*atoi(cantidadJugadores));
				
				//generamos el mazo del juego con orden aleatorio
				mazo = crearMazo();

				//colocamos una carta del mazo en el pozo.
				nodo* cartaInicial = obtener(mazo,0); //sacamos la primera carta 
				pozo = push(pozo, cartaInicial->dato, cartaInicial->dato2);
				mazo = borrarTipo(mazo, cartaInicial->dato,cartaInicial->dato2);

				//agrega los jugadores a una lista...
					//...los CPU...
					int t;
					for(t=0;t<atoi(cantidadJugadores)-1;t++)
					{
						jugadores = push(jugadores, JUGADOR_CPU,-1);
					}
					//...y al humano.
					jugadores = push(jugadores, JUGADOR_HUMANO,-1);

				//agregamos las manos
				int j,m;
				for(j=0;j<atoi(cantidadJugadores);j++){
					manos[j] = NULL;
					for(m=0; m<MANO_INICIAL;m++){
						//numero random
						
						//vemos una carta
						cartaInicial = obtener(mazo,0); //sacamos la primera carta
						//se coloca en la mano
						manos[j]= push(manos[j],cartaInicial->dato,cartaInicial->dato2);
						//se borra del mazo
						mazo = borrarTipo(mazo, cartaInicial->dato,cartaInicial->dato2);
					}
				}
				//muestra los turnos del juego antes de comenzar.
				muestraTurnos(jugadores);
			//borrar
				//printf("largo del mazo: %d\n", largo(mazo));
				//listarCartas(mazo);
			//fin borrar
				printf("\nPresione ENTER para comenzar la partida...");
				pausa();

				//terminamos condiciones pre-juego
				buclePreJuego = FALSE;
				//y vamos al bucle de turnos...
				bucleTurnosJuego = TRUE;
			}
		}
		//----------------------------------------------------------
		// FIN bucle pre-juego
		//==========================================================

		//==========================================================
		// BUCLE TURNOS DEL JUEGO
		//----------------------------------------------------------
		limpiar();
		int turno=-1; 	//turno actual
		char opcionJuego[STRING_MAX]; 	//entrada por teclado
		char sentido = 1; 	//sentido de los turnos (para cartas invertir)
		nodo* jugadorActual;	//jugador que le toca turno			

		while(bucleTurnosJuego){

			//verifica si quedan cartas en el mazo
			if(largo(mazo)<1){
				//si no hay cartas voltea el pozo
				mazo = volteaPozo(&mazo,&pozo);
			}
			turno = estableceTurno(atoi(cantidadJugadores),turno, sentido);
			//imprime estado del juego
			imprimeEstadoJuego(mazo,pozo);
			//obtiene el jugador que le corresponde el turno.
			jugadorActual = obtener(jugadores,turno);

			if( jugadorActual->dato == JUGADOR_HUMANO){
				printf("Tu turno!\n");
				//muestra la mano del jugador
				mostrarMano(manos[turno],"  ");
				//imprimirCartitas(largo(manos[turno]));

				//interaccion en turno
				printf("  Botar carta: ");
				fflush(stdin);
				fgets(opcionJuego,STRING_MAX,stdin);
				//reaccion a la opcion
					//==================================================
					// JUGADA DEL JUGADOR HUMANO
					//--------------------------------------------------

					//si el turno no es exitoso, no se avanza al siguiente jugador...
					if(!logicaTurno(&manos[turno], &mazo, &pozo, &turno, opcionJuego)){
						if(sentido){
							turno--;
						}
						else
							turno++;
					}
					else{
						if(largo(manos[turno])==0){
							limpiar();
							printf("\n\t\aFELICIDADES, HAS GANADO!!!\n\n");
							imprimeEstadoJugadores(jugadores,manos);
							printf("\n\t\aFELICIDADES, HAS GANADO!!!\n\n");
							bucleTurnosJuego = FALSE;
							printf("Presione [ENTER] para ontinuar...");
							pausa();
						}
					}
											
					//para salir
					if(atoi(opcionJuego) == -1){
						bucleTurnosJuego = FALSE;
					}
					//--------------------------------------------------
					// FIN jugada del jugador humano
					//==================================================
				//este "limpiar" permite que se vean solo las jugadas
				//de las CPU que se hacen hasta que le toca al usuario.
				limpiar();
			}
			else{
				//==========================================================
				//JUGADA AUTOMATICA DE COMPUTADORAS
				//----------------------------------------------------------
				printf("Turno Computadora %d, mano:", turno+1);
				imprimirCartitas(largo(manos[turno]));
				//si el turno no es exitoso, no se avanza al siguiente jugador...
				if(!jugadaAutomatica(&manos[turno], &mazo, &pozo, &turno)){
					if(sentido){
						turno--;
					}
					else
						turno++;
				}
				else{
					if(largo(manos[turno])==0){
						limpiar();
						imprimeEstadoJuego(mazo,pozo);
						printf("\n\t\aLA COMPUTADORA %d, HA GANADO!\n",turno+1);
						imprimeEstadoJugadores(jugadores,manos);
						printf("\n\t\aLA COMPUTADORA %d, HA GANADO!\n",turno+1);
						bucleTurnosJuego = FALSE;
						printf("Presione [ENTER] para continuar...");
						pausa();
					}
				}
				//-----------------------------------------------------------
				// FIN jugada automatica de computadoras
				//===========================================================
			}
		}
		//--------------------------------------------------------------
		// FIN bucle turnos juego
		//==============================================================

		//======================================
		// LIBERACION DE MEMORIA
		//--------------------------------------
		//liberamos lista de jugadores
		jugadores = anular(jugadores);
		//libera el mazo
		mazo = anular(mazo);
		//libarar el pozo
		pozo = anular(pozo);
		//libramos manos
		if(manos != NULL){
			int d;
			for(d=0; d < atoi(cantidadJugadores);d++){
				manos[d] = anular(manos[d]);
			}
			free(manos);	
		}
		//-------------------------------------
		// FIN liberacion memoria
		//=====================================
	}
	//--------------------------------
	// FIN bucle menu principal
	//================================
}