scieee AI-readable full text Open interactive document viewer

Estudio comparativo de modelos de identificación facial basados en correlación

Sierra Zapata, María

Abstract

El presente Trabajo Fin de Grado trata sobre el estudio comparativo de los modelos de identificación facial basados en correlación. Los objetivos a cumplir son: - Analizar los métodos de identificación facial más extendidos de una manera exhaustiva, desde su algoritmia matemática hasta su implementación informática. -Estudio comparativo, donde se incluyen aspectos como tasa de aciertos, falsos positivos o tiempos de identificación. Para ello, se ha realizado un estudio en profundidad de los modelos de identificación EigenFace, FisherFace y LBPHFace. Se contemplan para su realización cuatro variables: el tamaño de las muestras de los sujetos, el número de sujetos que formarán el modelo de identificación, el número de muestras por sujeto que forman el modelo y la estructura del modelo empleado. Se observará la influencia de las modificaciones de estas variables en los modelos de identificación. Tras la obtención de los resultados, se definirán los parámetros de tiempo y fiabilidad que cumple cada modelo. Por último, se finalizará este estudio con las conclusiones obtenidas de los resultados generados.

Full text

i Equation Chapter 1 Section 1 Trabajo Fin de Grado Grado en Ingeniería de las Tecnologías de Telecomunicación Estudio comparativo de modelos de identificación facial basados en correlación Autor: María Sierra Zapata Tutor: Eduardo Fernández Camacho Dep. Ingeniería de Sistemas y Automática Escuela Técnica Superior de Ingeniería Universidad de Sevilla Sevilla, 2015 iii Trabajo Fin de Grado Grado en Ingeniería de las Tecnologías de Telecomunicación Estudio comparativo de modelos de identificación facial basados en correlación Autor: María Sierra Zapata Tutor: Eduardo Fernández Camacho Catedrático Dep. Ingeniería de Sistemas y Automática Escuela Técnica Superior de Ingeniería Universidad de Sevilla Sevilla, 2015 v Trabajo Fin de Grado: Estudio comparativo de modelos de identificación facial basados en correlación Autor: María Sierra Zapata Tutor: Eduardo Fernández Camacho El tribunal nombrado para juzgar el Trabajo arriba indicado, compuesto por los siguientes miembros: Presidente: Vocales: Secretario: Acuerdan otorgarle la calificación de: Sevilla, 2015 El Secretario del Tribunal vii A todos los que han estado a mi lado durante estos años ix Agradecimientos Primero, quisiera agradecer este proyecto a mi tutor, Eduardo Fernández Camacho, por brindarme la oportunidad de realizarlo y que tanto me ha guiado durante la elaboración del mismo. También me gustaría mencionar a mis amigos, tanto de dentro como de fuera de la carrera. Me han acompañado durante este tramo de mi vida apoyándome y ayudándome a superar cada obstáculo. Aunque jamás te reconoceré que me ayudaras en aquel trabajo de programación de primero, Eugenio. Espero seguir contando con todos ellos en las próximas etapas de mi vida. Por último, quiero hacer una alusión especial a mi familia, que tanto ha sacrificado para poder encontrarme hoy aquí, realizando un último esfuerzo para terminar estos estudios. En especial, a dos personas que forman parte de ella. Mi hermana, Isabel, sin la cual no sabría que hacer. A pesar de todas las peleas y las riñas, al final es la persona con la que puedo contar para todo. Y mi pareja, Ramón, que a pesar de ser una incorporación reciente, para mí ya forma parte de mi familia. Consigue arrojar luz sobre los momentos de oscuridad y siempre está para levantarme en los momentos díficiles. Gracias por este maravilloso tiempo junto a ti que espero poder disfrutar siempre. Figura 30. Porcentajes de falsos positivos en hombres del modelo LBPHFace 33 Figura 31. Porcentajes de tasas de acierto del modelo EigenFace. 34 Figura 32. Porcentajes de tasas de acierto del modelo FisherFace. 34 Figura 33. Porcentajes de tasas de acierto del modelo LBPHFace. 35 Figura 34. Porcentajes de tasas de acierto en mujeres del modelo EigenFace. 35 Figura 35. Porcentajes de tasas de acierto en mujeres del modelo FisherFace. 36 Figura 36. Porcentajes de tasas de acierto en mujeres del modelo LBPHFace. 36 Figura 37. Porcentajes de tasas de acierto en hombres del modelo EigenFace. 37 Figura 38. Porcentajes de tasas de acierto en hombres del modelo FisherFace. 37 Figura 39. Porcentajes de tasas de acierto en hombres del modelo LBPHFace. 38 xvii Notación TFG Trabajo Fin de Grado PCA Principal Component Analysis LDA Linear Dimension Analysis LBP Local Binary Patterns e.o.c En otro caso LBPH Local Binary Patterns Histograms GHz Gigahercios L3 Level 3 MB Megabytes RAM Random Access Memory GB Gigabytes DDR3 Double Data Rate type 3 ” Pulgadas GUFD Glasgow Unfamiliar Face Database ISO International Organization for Standardization GCC GNU Compiler Collection Mat Tipo definido por OpenCV para contener la información relativa a una imagen 1 1 INTRODUCCIÓN l problema de la identificación facial se ha planteado desde múltiples puntos de vista. De esta manera, ha sido implementado en aplicaciones de diversos ámbitos. La identificación facial es empleada en áreas que abarcan desde la seguridad informática hasta el entretenimiento personal. Un ejemplo, dentro del área de seguridad, se tiene en los teléfonos móviles. Estos dispositivos contienen formas diferentes para realizar un patrón de desbloqueo, requiriendo una de ellas el uso de la identificación facial. Este proyecto versa sobre el funcionamiento de los modelos de identificación facial basados en correlación. Realizando un estudio en profundidad sobre estos modelos, se quiere dar con las respuestas a preguntas como cuánto tiempo se tarda en realizar una identificación, cuál es la tasa de falsos positivos del modelo o cómo de fiables son dichos métodos. A través de la comparación de los resultados que se obtengan a lo largo de este estudio, se hallarán los parámetros que rigen el funcionamiento de los modelos. Se tendrán cuatro variables: el tamaño de las muestras de los sujetos, el número de sujetos que formarán el modelo de identificación, el número de muestras por sujeto que forman el modelo y la estructura del modelo empleado. 1.1. Motivación La Visión Artificial es un mercado en auge. Desde que se hicieran accesibles las librerías de desarrollo de este ámbito, el número de aplicaciones existentes en torno a esta rama no hace más que aumentar. Dentro de la Visión Artificial, se encuentra el reconocimiento y la identificación facial, siendo esta última el dominio de estudio de este proyecto. Así pues, la motivación que va ligada a este trabajo es realizar un estudio en profundidad, comparando los modelos existentes para la identificación facial basados en correlación. Conociendo el comportamiento de estos modelos, se puede elegir el mejor método a utilizar cuando se desee desarrollar una aplicación de identificación facial. De esta forma, se podrá decidir la implementación del modelo a través de los parámetros que se quieran cumplir. E “I learned that computer sciense is not just about syntax and coding. We can make a difference in people’s lives by developing applications.” - Kyle Rector - Introducción 2 2 1.2. Objetivos  Analizar los métodos de identificación facial más extendidos de una manera exhaustiva, desde su algoritmia matemática hasta su implementación informática.  Estudio comparativo, donde se incluyen aspectos como tasa de aciertos, falsos positivos o tiempos de identificación. Para alcanzar estos objetivos, se realizará una implementación de dicho estudio, la cual generará una base de datos con los resultados de todas las variantes de los modelos empleados. Obtenidos los resultados, serán procesados para así obtener los parámetros que gobiernan dichos modelos para su posterior análisis. 1.3. Metodología Se realizará un estudio sobre los modelos de identificación existentes en OpenCV [1]. Existen tres modelos: modelo FisherFace, modelo EigenFace y modelo LBPHFace. Se evaluarán tanto en su forma simple como en una estructura en árbol. En total, se analizarán seis modelos. Se tendrá una base de datos con cien sujetos, la mitad hombres y la otra mitad mujeres [2]. El estudio se realizará sobre diez, cincuenta y cien clases clasificadoras. Una clase clasificadora es un sujeto único a identificar. Se comparará cómo afecta el hecho de tener imágenes más pequeñas o más grandes en el modelo, una imagen o dos imágenes por sujeto y el número de clases clasificadoras a la hora de construir el modelo. Así, se obtendrán los parámetros siguientes:  Tiempo de creación del modelo.  Tiempo de carga del modelo.  Tiempo de identificación medio del modelo.  Porcentaje de falsos positivos.  Porcentaje de falsos positivos en mujeres.  Porcentaje de falsos positivos en hombres.  Porcentaje de tasa de acierto.  Porcentaje de tasa de acierto en mujeres.  Porcentaje de tasa de acierto en hombres. 1.4. Estructuración del proyecto  El capítulo 2 desarrolla en mayor profundidad qué es la visión artificial y el reconocimiento facial. Además, se definirá cada modelo de identificación.  El capítulo 3 muestra las herramientas empleadas para el desarrollo del estudio a nivel hardware y software.  El capítulo 4 está compuesto por la implementación del estudio. Se definirá la interfaz del estudio, la programación de visión artificial realizada y cómo se guardan los datos generados.  El capítulo 5 contiene la implementación para la representación gráfica de los resultados obtenidos y las gráficas generadas.  Por último, en el capítulo 6 se encuentran las conclusiones obtenidas tras la realización de este estudio y se presentan posibles vías de futuro. 3 2 VISIÓN ARTIFICIAL l término Visión Artificial ha sido utilizado a lo largo de toda la introducción. Sin embargo, ¿qué es la Visión Artificial? La Visión Artificial es un campo de la Inteligencia Artificial [3]. Mediante modelos matemáticos intenta conseguir la percepción realizada por el sentido de la vista. Es decir, trata de obtener información a través del procesado de imágenes. Se intentan extraer características relevantes visuales haciendo uso de procedimientos automáticos. La información extraída puede ser muy variada. No solo se obtienen propiedades físicas, como puede ser el tamaño, la forma o la localización de un objeto, sino también propiedades del material (color, textura...) o qué se está identificando (un objeto, una persona, un animal...). Normalmente, la información extraída debe de cumplir una serie de requisitos. Se deben tener en cuenta las tasas de fallos, los falsos positivos y los falsos negativos que conllevan la utilización de este tipo de algoritmia. La Visión Artificial no es perfecta y hay que tratar de minimizar el impacto de este tipo de errores en el sistema. A pesar de no ser perfecta, la Visión Artificial es muy eficaz en tareas visuales repetitivas y alineantes para el hombre. Por ello, es aplicada en muchos sectores diferentes. En sectores como la industria, se utiliza para la inspección de piezas, sobre todo para que pasen pruebas de calidad de forma automática. También es utilizada en vehículos autoguiados, para determinar la trayectoria del vehículo. En la actualidad, ya no solo es exclusiva para la industria. Existen muchas aplicaciones a nivel de usuario, como ya se ha mencionado en la introducción. Otro ejemplo de ello es que algunos dispositivos móviles tienen la capacidad de ordenar las imágenes de la galería por los sujetos que aparecen en ellas y agrupar todas las imágenes de un mismo sujeto en una carpeta solo para dicho sujeto. Esta última aplicación pertenece a la rama del reconocimiento y la identificación facial dentro de la Visión Artificial. En las próximas secciones de este capítulo, se hablará de dicha rama y se explicará la base y fundamentación de los métodos y modelos en los que se basan la identificación facial. La versatilidad de aplicaciones en las que participa la Visión Artificial hace que sea una rama muy interesante de estudio. E Visión Artificial 4 4 2.1. Reconocimiento e identificación facial El reconocimiento y la identificación facial conllevan dos fases en Visión Artificial. Primero, se debe encontrar a una persona en la imagen a examinar y, a continuación, proceder a la identificación de dicha persona comparándola con una base de datos, todo ello de forma automática. Es importante diferenciar ambos procesos, ya que el presente estudio solo se implicará en la segunda parte, la identificación facial. Grandes empresas hacen uso de este tipo de algoritmia. Mastercard ha desarrollado una aplicación para que a la hora de pagar con la tarjeta, se valide que es el propietario de la tarjeta el que está realizando la compra[4]. Facebook incluye este tipo de métodos también, cuando preselecciona dónde se encuentra una cara o sugiere cuál de tus amigos es el que se encuentra en el recuadro. El principal problema de la identifiación facial es que se trata de biométrica. Los algoritmos empleados en esta rama de la Visión Artificial son muy susceptibles a los cambios de iluminación, tamaño de las imágenes, calidad de las imágenes… sin contar con los cambios físicos de las personas, como es el caso a estudiar. Cambios como la barba, el color del pelo o el llevar gafas pueden afectar en la identificación. Es necesario estudiar y definir todas las variables implicadas en este proceso. Conociéndolas, se puede realizar un sistema más robusto frente a cambios de este tipo. Hay que comprender la base de los modelos para poder utilizarlos de la forma más adecuada posible. Saber el modelo de identificación más adecuado para la aplicación que se desee crear también es importante. Existen dos grandes agrupaciones, en cuanto a modelos de identificación facial se refiere: los modelos basados en caracteríscas geométricas de la cara y los modelos basados en correlación. Los modelos basados en características geométricas son los más intuituivos [5]. Uno de los primeros sistemas de reconocimiento facial automatizado utilizaba puntos de marcado (posición de los ojos, de las orejas, de la nariz…) para construir un vector de características (distancia entre los puntos, ángulo entre ellos…) [6]. El reconocimiento se realiza calculando la distancia euclídea entre las características de la imagen de prueba y la imagen de referencia. Este método es robusto contra los cambios de iluminación, pero tiene un enorme inconveniente: el registro exacto de los puntos de marcado es complicado. Uno de los últimos métodos implementados basados en geométrica facial demuestran que por sí solo este tipo de método no conlleva suficiente información para el reconocimiento facial [7]. Los modelos basados en correlación son los elegidos en el desarrollo de este esutdio. Para realizar la identificación utilizando las librerías de código abierto de Visión Artificial, OpenCV [1], existen tres tipos diferentes de modelos. Se desarrollará el modelo matemático de cada uno de ellos, explicando su fundamento y funcionamiento paso a paso. Los tres modelos son:  Modelo EigenFace.  Modelo FisherFace.  Modelo LBPHFace. 2.1.1. Modelo EigenFace El principal problema de la representación de imagénes es su alta dimensionalidad [5]. Imágenes en blanco y negro con dos dimensiones ocupan un vector con un tamaño . La cuestión es, ¿todos los datos de dichos vectores son necesarios? Solo se puede tomar una decisión cuando existe una variación en los datos. Por tanto, se busca la información más relevante. El Análisis de Componente Principal [8] (PCA en inglés) se encarga de que un conjunto de variables posiblemente correladas se conviertan en un conjunto de variables incorreladas. Los métodos PCA encuentran la dirección con la mayor varianza en los datos, llamados componentes principales.  Descripción del algoritmo Suponga un vector aleatorio con observaciones . 5 5 Estudio comparativo de modelos de identificación facial basados en correlación 1. Compute la media 2. Compute la Covarianza Matriz 3. Compute los autovalores y los autovectores de 4. Ordene los autovectores de forma descendiente por su autovalor. Los componentes principales son los autovectores correspondientes a los mayores autovalores . Los componentes principales del vector observado son dados por: donde . La reconstrucción desde las bases PCA se hace con: donde .  Resumen del método El método EigenFace realiza la identificación facial: - Proyectando todas las muestras a entrenar en el subespacio PCA. - Proyectando la imagen a identificar en el subespacio PCA. - Encontrando el vecino más cercano entre la proyección de las imágenes entrenadas y la proyección de la imagen a identificar. 2.1.2. Modelo FisherFace El PCA, que es la base del método EigenFace, encuentra combinaciones lineales de características que maximicen la varianza total en los datos [5]. Aunque es claramente una manera bastante poderosa para representar datos, no implica que no pueda perderse mucha información cuando se utiliza ese método. Imagine una situación donde la varianza de los datos es generada por una fuente externa, como puede ser la iluminación. Los componentes identificados por un PCA no contiene ninguna información discriminativa, así que las muestras proyectadas se correlan juntas y la clasificación, por tanto, es imposible de realizar (en [9] se puede encontrar un ejemplo). El Análisis Discriminatorio Lineal (LDA en inglés) consigue una reducción en la dimensionalidad de una especificación de una clase. Fue creado por el estadístico Sir R.A. Fisher [10]. Para poder encontrar la combinación de las características que diferencian mejor las clases, el LDA maximiza la proporción entre las clases y la dispersión de las clases, en vez de maximizar simplemente la dispersión total de las clases. La idea es simple: una clase debe agrupar su proyección lo más pegada posible, mientras que las diferentes clases existentes deben estar tan alejadas unas de otras como sea posible en la representación de las proyecciones. Esto fue reconocido, también, por los investigadores Belhumeur, Hespanha y Kriegman, que aplicaron el LDA en reconocimiento facial en [11]. Visión Artificial 6 6  Descripción del algoritmo Sea un vector aleatorio con las muestras dibujadas de clases: Las matrices de dispersión y se calculan como: donde es la media total: y es la media de la clase : El algoritmo clásico Fisher ahora busca, para una proyección , maximizar el criterio de separación entre clases: Siguiendo la referencia [11], se obtiene una solución para esta optimización del problema, resuelta por el Problema de Autovalor General: Queda un problema por resolver: El rango de es al menos , con muestras y clases. En los problemas del patrón de reconocimiento, el número de muestras es casi siempre menor que la dimensión de los datos de entrada (el número de píxeles), así que la matriz de dispersión se convierte en singular (ver [12]). En [11], se resuelve realizando un PCA en los datos proyectando las muestras en el espacio de dimensiones . Un LDA puede realizarse a continuación para reducir los datos, ya que ya no es singular. La optimización del problema, por tanto, puede ser reescrita como: La transformación de la matriz , que proyecta la muestra en el espacio dimensional , es dada por: 7 7 Estudio comparativo de modelos de identificación facial basados en correlación 2.1.3. Modelo LBPHFace Los modelos EigenFace y FisherFace toman un enfonque holístico para la identificación fácil. La información es tratada como un vector con un espacio dimensional muy alto [5]. El enfoque realizado por EigenFace maximiza la dispersión total, el cual puede conllevar problemas si la varianza se debe por una fuente externa, ya que los componentes con una varianza máxima sobre todas las clases existentes no son necesariamente útiles para la clasificación [9]. Para preservar alguna información discriminatoria, se aplica el LDA y se optimiza, como se describió para el modelo FisherFace. Ahora, la idea no es mirar la imagen por completo como un vector con una gran dimensionalidad, sino describir solo las características locales de un objeto. Las características que se extraen de esta forma tendrán una baja dimensionalidad implícitamente. En esto se basa el operador de Patrones Binarios Locales (LBP en inglés). Se basa en el análisis de texturas en 2D. La idea principal de LBP es resumir la estructura local de una imagen mediante la comparación de cada píxel con sus píxeles vecinos. Se toma un píxel como centro y se limita el valor de los vecinos. Es decir, si la intensidad del píxel central es mayor que su vecino, este se denota con un cero, y si, por el contrario, la intensidad del vecino es mayor o igual a la intensidad del vecino central, entonces se denota con un uno. Figura 1. Ejemplo de cómo funciona el operador LBP  Descripción del algoritmo Una descripción más formal del operador LBP se puede dar como: con como el píxel central con intensidad ; e la intensidad del píxel vecino. es la función signo definida como: Esta descripción permite capturar detalles con mucha precisión en las imágenes [13]. Para un punto , la posición de su vecino , , pude ser calculado como: donde es el radio del círculo que forman los vecinos y es el número de puntos de muestra. El operador es una extensión de la codificación original LBP, por eso a veces es llamado LBP Extendido. Si los puntos coordenados en el cícurlo no correponden a las coordenadas de la imagen, el punto debe ser interpolado. OpenCV implementa una interpolación bilineal: Por definición, el operador LBP es robusto frente a transformaciones en escala de grises monótonas. Por último, se incorpora la información espacial en el modelo de identificación facial. La representación Implementación del Estudio 14 14 Figura 2. Relación temporizadores-tareas desempeñadas Una vez finalizado el contructor de la clase QFormPrincipal, se procede al resto de fases del estudio. La primera de ellas es la fase de la creación de todos los modelos identificadores implicados en este estudio. Durante la duración de esta fase, la interfaz tiene este aspecto: Figura 3. Interfaz durante la creación de modelos. Creados y guardados todos los modelos, la siguiente fase es la de carga de un modelo: Figura 4. Interfaz durante la carga de un modelo. 15 15 Estudio comparativo de modelos de identificación facial basados en correlación Y, después de cargar el modelo, se procede a la identificación de la base de datos de sujetos: Figura 5. Interfaz durante la identificación de la base de datos. La imagen anterior se mantiene mientras se procede a la identificación de los 100 sujetos que componen la base. Estas dos fases, cargando modelo e identificando, se repite hasta que se hayan identificado los 100 sujetos con cada uno de los modelos. En este estudio, en total hay seis modelos. Identificados los sujetos de un modelo, se guardan los datos generados en un fichero. Cuando se termina la identificación de los seis modelos, se procede al cierre del estudio. Se guardan los tiempos de creación y carga de los modelos en un archivo y se procede al cierre de la aplicación: Figura 6. Interfaz cuando se finaliza el estudio. En el útlimo punto de este capítulo se hablará con mayor profundidad de los ficheros con los datos generados a lo largo del estudio. A lo largo de las fases anteriores es cuando se da la comunicación entre los hilos. El hilo principal, durante la creación de modelos, emite seis señales distintas para crear cada uno de los seis modelos de identificación facial. Durante la creación de cada modelo, se activa el temporizador3 (timer3) para medir los tiempos de creación de los modelos. Creado el modelo, el hilo proceso emite una señal de fin de creación de modelo. Recibida por el hilo principal, reestablece el temporizador3 y emite la señal para crear el siguiente modelo. Una vez creados los seis modelos, se puede proceder a la carga del primer modelo. Implementación del Estudio 16 16 Para ello, el hilo principal emite una señal, al igual que ocurría en el caso de creación, pero indicando la carga del modelo. Y, como antes, el tiempo de carga también es controlado por el temporizador3. Aunque, a diferencia de la creación de modelos, cuando el hilo proceso emite la señal de fin de carga, empieza la identificación de los 100 sujetos. Realizada la identificación de todos los sujetos, se procede a la carga del siguiente modelo de la misma forma. Un esquema de la comunicación entre hilos se muestra en la siguiente figura: Figura 7. Esquema comunicación hilos. Explicado todo el código que conlleva la interfaz, queda explicar la parte de Visión Artificial, la clase QProceso. 4.2. Programación de Visión Artificial El procesado de la parte de Visión Artificial está definido en las funciones que forman la clase QProceso. Son tres las tareas de Visión Artificial que realiza QProceso:  Crear y guardar los seis modelos.  Cargar los modelos.  Realizar la fase de identificación. Los seis modelos empleados son: el modelo EigenFace, el modelo FisherFace y el modelo LBPHFace, todos en su forma simple y con estructura en árbol.  Descripción de los modelos en su forma simple Todos los modelos utilizan las mismas funciones para desempeñar las tareas arriba descritas. La única diferencia existente está en la creación del modelo. Cada modelo se crea de una forma distinta: - Creación del modelo EigenFace: model = createEigenFaceRecognizer(); - Creación del modelo FisherFace: model = createFisherFaceRecognizer(); - Creación del modelo LBPHFace: model = createLBPHFaceRecognizer(); 17 17 Estudio comparativo de modelos de identificación facial basados en correlación Realizada la creación, se tiene un modelo vacío. Para tener un modelo capaz de identificar, se debe entrenar. Se utiliza la función train: model->train(images,labels); Los parámetros de entrada corresponden a: - images: vector de Mat. Contiene las muestras utilizadas por el modelo de los diferentes sujetos. - labels: vector de enteros. Relaciona el número de la clase correspondiente a un sujeto con la imagen de muestra que se encuentra en la misma posición dentro del vector de Mat. Ya se tiene un modelo capaz de identificar. Se puede proceder, por tanto, a guardar el modelo con la función save, así podrá cargarse y ser utilizado para identificar: model->save(fn_model); fn_model hace referencia al nombre con el que se desea guardar el modelo. Al tenerse el modelo completo creado, puede emitirse la señal de fin de creación del modelo. Un ejemplo de los pasos de la función completa para la creación de un modelo se puede ver a continuación (se utiliza como ejemplos el modelo EigenFace): 73 //Creacion del modelo 74 model = createEigenFaceRecognizer(); 75 model->train(images,labels); 76 77 //Se guarda el modelo creado 78 model->save(fn_model); 79 80 //Emision de la señal de fin de creacion del modelo 81 emit SignalFinCreacionModelo(); 82 model->~FaceRecognizer(); Para cargar un modelo, se hace uso de la función load. La función load tiene como parámetro de entrada el mismo que la función save. Hay que crear un modelo vacío antes de proceder a la carga. Así, se tiene para cargar un modelo la función siguiente: 111 //Carga del modelo 112 model = createEigenFaceRecognizer(); 113 model->load(fn_model); 114 115 //Emision de la señal de fin de carga del modelo 116 emit SignalFinCargaModelo(); Al igual que cuando se creaba, una vez está cargado el modelo y listo para su utilización emite una señal indicándolo. Por último, para realizar la identificación se utiliza la función predict: model->predict(test_im,predictedLabel,confidence); Los parámetros de entrada son: - test_im: Imagen del sujeto a identificar. - predictedLabel: Entero donde se guardará la predicción de la clase a la que pertenece el sujeto a identificar. - confidence: Decimal en el que se guardará la confianza con la que se ha hecho la predicción. Como pasaba en las funciones anteriores, al terminar la identificación se emite una señal indicándolo, tal y como se muestra en la función completa del proceso de identificación: 131 //Identificacion del sujeto 132 predictedLabel=-1; Implementación del Estudio 18 18 133 confidence=0.0; 134 model->predict(test_im,predictedLabel,confidence); 135 136 //Emision de la señal de fin de identificacion del sujeto 137 emit SignalFinIdentificacion(confidence,predictedLabel);  Descripción de los modelos con estructura en árbol Al igual que en la forma simple, se crea el árbol, se guarda, se carga y se utiliza para identificar. Aunque ahora ya no se tiene un único modelo, sino un vector de modelos. Cada modelo representa una de las ramas que conforman el árbol. El árbol está formado por ramas con modelos binarios y ramas con modelos de cinco clases. Esto es debido a que, para la formación de los modelos, se han usado 10, 50 y 100 clases identificadoras, siendo estos múltiplos de dos y de cinco. Todas los modelos que conforman las ramas de un árbol están creados con el mismo tipo de modelo. Así, si se trata de una estructura árbol con modelo EigenFace, todos los modelos creados para las diferentes ramas serán de este tipo de modelo. Lo mismo ocurre para la estructura en árbol con modelo FisherFace y la estructura en árbol con modelo LBPHFace. Crear un modelo que compone una rama del árbol es como crear un modelo simple. Siguen los mismos pasos. La primera diferencia reside en que, a medida que se avanza en la creación de los modelos que componen el árbol, cada vez se tiene un menor número de sujetos para formar el modelo. En el siguiente ejemplo se muestra cuántos sujetos componen cada modelo de cada rama para el caso de 10 clases identificadoras: Figura 8. Modelos creados para un árbol con 10 clases identificadoras. La otra diferencia reside en que, en el caso de los modelos binarios, como su nombre indica, solo se tienen dos clases identificadoras, y los modelos con cinco clases, pues tienen cinco clases identificadoras. Al final, dependiendo de la predicción de cada modelo, se irán recorriendo las ramas del árbol hasta llegar a la identificación del sujeto, tal como se puede ver en la siguiente figura, en el caso de tener 10 sujetos para formar el modelo: Figura 9. Estructura en árbol con 10 clases identificadoras. 19 19 Estudio comparativo de modelos de identificación facial basados en correlación Todo lo anteriormente explicado ha sido implementado en funciones. A continuación, se muestra el diagrama que sigue la función de creación el árbol: Figura 10. Diagrama de creación de estructura en árbol. El proceso de carga es el siguiente: Figura 11. Diagrama de carga de estructura en árbol. Implementación del Estudio 20 20 Por último, el proceso de identificación llevado a cabo por la estructura en árbol: Figura 12. Diagrama de identificación de estructura en árbol. 4.3. Datos generados Los experimientos que se han realizado han sido los siguientes:  Influencia del tamaño de la imagen en los modelos. Se han utilizado cuatro tamaños distintos en las muestras tomadas de los sujetos: 50x50 píxeles, 100x100 píxeles, 150x150 píxeles y 200x200 píxeles.  Influencia del número de sujetos para formar el modelo de identificación. Se han usado 10, 50 y 100 sujetos para la creación de los modelos.  Influencia del número de imágenes por sujeto. Cómo influye el tener una o dos imágenes por sujeto en los modelos.  Influencia en el uso de un modelo simple o con estructura en árbol con cada tipo de modelo existente. Se van a evaluar seis modelos distintos. En total se tienen 144 variantes a estudiar, todas ellas integradas en este estudio. Debido a todas las variantes, se ha generado un gran número de datos. Estos datos han sido escritos en ficheros. A continuación se presentan los ficheros que se han obtenido:  24 ficheros que contienen los tiempos de creación y carga de los modelos.  216 ficheros que contienen los datos generados por la identificación de los sujetos femeninos.  216 ficheros que contienen los datos generados por la identificación de los sujetos masculinos. Todos estos ficheros han sido escritos por la clase QConfig. 21 21 Estudio comparativo de modelos de identificación facial basados en correlación El primer tipo de fichero es el que contiene los tiempos de creación y de carga. Dichos tiempos son los tiempos de los seis modelos que se han creado y cargado durante una de las ejecuciones de la aplicación. Este fichero se genera tras la ejecución de las variantes de tamaño, número de sujeto para los modelos y número de imágenes por sujeto. Los ficheros con los datos debido a la identificación de mujeres han sido generados cada vez que un modelo identificaba a los cincuenta sujetos femeninos que se tienen en la base de datos utilizada. Se generan más de 144 ficheros ya que cuando se usa solo una imagen por sujeto, se procede a identificar las dos imágenes que se tienen de cada sujeto. Debido a esto, es por lo que se obtienen 216 archivos. Los ficheros con los datos de las identificaciones masculinas se generan de la misma manera que los ficheros con los datos de identificación femenina. Por ello, se obtiene el mismo número de archivos para el caso femenino y para el caso masculino. Cada tipo de fichero es generado por funciones distintas definidas en la clase QConfig. Por tanto, la clase QConfig contiene en total cuatro funciones:  Función encargada de la lectura del archivo de configuración de la interfaz.  Función encargada de la escritura del archivo con los tiempos de creación y de carga de los modelos.  Función encargada de la escritura del archivo con los datos de identificación de los sujetos femeninos.  Función encargada de la escritura del archivo con los datos de identificación de los sujetos masculinos. Implementación del Estudio 22 22 23 5 REPRESENTACIÓN DE RESULTADOS eniendo todos los datos recogidos en ficheros, el siguiente paso es extraer dichos resultados, sintetizarlos y respresentarlos gráficamente. Así, en el último capítulo, se comentarán las conclusiones obtenidas por la realización de este estudio. Debido a la gran cantidad de ficheros con datos a procesar, se hace uso de MATLAB [16] para realizar estas tareas. MATLAB es capaz de procesar grandes cargas computacionales de una forma rápida. Además, dispone de herramientas de representación gráfica. A lo largo de este capítulo, se explicará el código creado en MATLAB, adjunto en el Anexo C; los datos obtenidos para la representación gráfica y, por último, se incluirán todas las gráficas que contendrán todos los resultados obtenidos. 5.1. Programación en MATLAB Para la representación gráfica en MATLAB, han sido creado los siguientes ficheros, todos adjuntos en el Anexo C:  analizaFicheroTiempos.m: Abre todos los ficheros que contienen los tiempos de creación y de carga de los modelos, haciendo uso de la función leeFicheroTiempos. Realiza la representación de dichos tiempos en gráficas. Dichas gráficas enfrenta los datos de los distintos tamaños de imagen utilizados, el número de sujetos empleados en el modelo, si se tiene una o dos imágenes por sujeto y la estructura simple con la estructura en árbol.  leeFicheroTiempos.m: Fichero que contiene la función leeFicheroTiempos. Devuelve en una matriz los datos contenidos en el fichero de entrada.  analizaFicheroPersona50x50.m: Realiza la lectura y síntesis de todos los datos obtenidos de las identificaciones, tanto los ficheros de sujetos masculinos como los ficheros de sujetos femeninos, con un tamaño de muestra de 50x50 píxeles. Para ello, hace uso de la función leeFicheroPersona.  analizaFicheroPersona100x100.m: Realiza la lectura y síntesis de todos los datos obtenidos de las identificaciones, tonto los ficheros de sujetos masculinos como los ficheros de sujetos femeninos, con un tamaño de muestra de 100x100 píxeles. Para ello, hace uso de la función leeFicheroPersona. T Representación de resultados 30 30 Figura 23. Porcentajes de falsos positivos del modelo FisherFace Figura 24. Porcentajes de falsos positivos del modelo LBPHFace. 31 31 Estudio comparativo de modelos de identificación facial basados en correlación  Porcentajes de falsos positivos en mujeres Figura 25. Porcentajes de falsos positivos en mujeres del modelo EigenFace. Figura 26. Porcentajes de falsos positivos en mujeres del modelo FisherFace. Representación de resultados 32 32 Figura 27. Porcentajes de falsos positivos en mujeres del modelo LBPHFace.  Porcentajes de falsos positivos en hombres Figura 28. Porcentajes de falsos positivos en hombres del modelo EigenFace. 33 33 Estudio comparativo de modelos de identificación facial basados en correlación Figura 29. Porcentajes de falsos positivos en hombres del modelo FisherFace. Figura 30. Porcentajes de falsos positivos en hombres del modelo LBPHFace Representación de resultados 34 34  Porcentajes de tasas de acierto Figura 31. Porcentajes de tasas de acierto del modelo EigenFace. Figura 32. Porcentajes de tasas de acierto del modelo FisherFace. 35 35 Estudio comparativo de modelos de identificación facial basados en correlación Figura 33. Porcentajes de tasas de acierto del modelo LBPHFace.  Porcentajes de tasas de acierto en mujeres Figura 34. Porcentajes de tasas de acierto en mujeres del modelo EigenFace. Representación de resultados 36 36 Figura 35. Porcentajes de tasas de acierto en mujeres del modelo FisherFace. Figura 36. Porcentajes de tasas de acierto en mujeres del modelo LBPHFace. 37 37 Estudio comparativo de modelos de identificación facial basados en correlación  Porcentajes de tasas de acierto en hombres Figura 37. Porcentajes de tasas de acierto en hombres del modelo EigenFace. Figura 38. Porcentajes de tasas de acierto en hombres del modelo FisherFace. Representación de resultados 38 38 Figura 39. Porcentajes de tasas de acierto en hombres del modelo LBPHFace. 39 6 ASPECTOS FINALES btenidos todos los resultados de forma gráfica, durante este último capítulo se procederá a comentar las conclusiones más relevantes extraídas. Por último, y para concluir esta memoria, se añadirán las posibles vías de futuro. 6.1. Conclusiones Comparando los tiempos de creación y de carga de los modelos, se observa que el primero es mayor que el segundo. Se tarda más en crear un modelo que en que éste sea cargado. La acción de crear un modelo solo es necesaria la primera vez. Una vez éste se ha guardado, puede ser cargado y utilizado tantas veces como se quiera. Además, cuando se carga, se puede dejar funcionando el modelo tanto tiempo como se quiera. No es necesario estar continuamente recargándolo para realizar la identificación. El siguiente parámetro de interés es el tiempo medio de identificación. Es muy importante, ya que dependiendo del tipo de aplicación que se quiera desarrollar, se deberá usar un modelo u otro. Por ejemplo, si se quiere una aplicación en la que se identifiquen personas sin necesidad de que sea en tiempo real, se puede escoger el método más fiable aunque sea más lento. Por el contrario, si se desea realizar una aplicación en tiempo real con varias identificaciones por imagen, se deberá escoger aquella cuyo tiempo de identificación medio no supere el tiempo de toma de muestra de la cámara. Otro aspecto a tener en cuenta para el tiempo medio de identificación es el número de sujetos que forman la base de datos a utilizar. Cuanto mayor sea el número de sujetos, mayor será este tiempo. Por ello, llega un momento en la que el modelo simple necesita realizar tantas iteraciones que supera el tiempo medio de identificación del modelo con estructura en árbol. Este caso solo se consigue observar en el modelo FisherFace, pero es extrapolable a los demás modelos. No se llega a observar debido a que el número de sujetos es muy bajo. Queda por evaluar la fiabilidad de los modelos. Lo primero que se observa es cómo se mejora la tasa de acierto en casi todos los modelos cuando se tienen dos muestras por sujeto. Es un cambio bastante signficativo, ya que, en la gran mayoría, dicha tasa mejora entre un 10% y un 20%. Claro está, mayor número de muestras implica un mayor tiempo medio de identificación. Aún así, en el estudio llevado a cabo, el máximo tiempo medio de identificación es de 0.1 segundos, valor bastante asumible cuando se traten de aplicaciones de identificación en tiempo real. O Anexo A. Documentación del código (Doxygen) 46 46 47 47 Estudio comparativo de modelos de identificación facial basados en correlación Documentación de las clases Referencia de la Clase QConfig Se encarga de la lectura del fichero de configuracion para la interfaz de la aplicacion y la escritura de los ficheros con los datos generados por los distintos modelos de identificacion. #include <Config.h> Métodos públicos  QConfig () Constructor de la clase QConfig.  virtual ~QConfig () Destructor de la clase QConfig.  void Inicializar () Funcion Inicializar.  void CargarArchivo (int indice) Funcion CargarArchivo. Carga el archivo con los valores de configuracion de la interfaz de la aplicacion.  void EscribeValoresMujer (int id_modelo, int id_CSV) Funcion EscribeValoresMujer. Escritura de los valores de identificacion de sujetos femeninos.  void EscribeValoresHombre (int id_modelo, int id_CSV) Funcion EscribeValoresHombre. Escritura de los valores de identificacion de sujetos masculinos.  void EscribeTiemposModelos (int id_CSV) Funcion EscribeTiemposModelos. Escritura de los valores de los tiempos por creacion y carga. Atributos públicos  QString background  int resolucion_w  int resolucion_h  int label_personas_x  int label_personas_y  int label_personas_w  int label_personas_h  int label_personas_marg  int label_personas_spac  int frame_tiempos_x  int frame_tiempos_y  int frame_tiempos_w  int frame_tiempos_h  int frame_tiempos_marg  int frame_tiempos_spac  float seg_CSV  vector< float > seg_Modelos  vector< float > seg_Carga  vector< float > media_segundos  vector< float > confidence  vector< int > prediccion Atributos privados  QSettings * settings Anexo A. Documentación del código (Doxygen) 48 48 Descripción detallada Se encarga de la lectura del fichero de configuracion para la interfaz de la aplicacion y la escritura de los ficheros con los datos generados por los distintos modelos de identificacion. Documentación del constructor y destructor QConfig::QConfig () Constructor de la clase QConfig. Constructor vacio. 14 { 15 16 } QConfig::~QConfig ()[virtual] Destructor de la clase QConfig. Destructor vacio. 19 { 20 21 } Documentación de las funciones miembro void QConfig::CargarArchivo (int indice) Funcion CargarArchivo. Carga el archivo con los valores de configuracion de la interfaz de la aplicacion. Lectura del fichero de configuracion de la interfaz de la aplicacion. Inicializacion de las variables de configuracion usadas para realizar la interfaz de la aplicacion.  Parámetros: indice Entero con el que se controla el archivo de configuracion a cargar. 29 { 30 //Apertura del fichero a leer 31 QString nombre_fichero = QString("etc/Config_%1.inp").arg(indice); 32 settings = new QSettings(nombre_fichero, QSettings::IniFormat); 33 qDebug() << "Cargando archivo " << nombre_fichero; 34 35 //Lectura del nombre de la imagen de background 36 settings->beginGroup("GENERALES"); 37 background = settings->value("background").toString(); 38 settings->endGroup(); 39 40 //Lectura de las propiedadess a configurar en la interfaz de la aplicacion 41 settings->beginGroup("INTERFAZ"); 42 resolucion_w = settings->value("resolucion_w").toInt(); 43 resolucion_h = settings->value("resolucion_h").toInt(); 44 45 label_personas_x = settings->value("label_personas_x").toInt(); 46 label_personas_y = settings->value("label_personas_y").toInt(); 47 label_personas_w = settings->value("label_personas_w").toInt(); 48 label_personas_h = settings->value("label_personas_h").toInt(); 49 label_personas_marg = settings->value("label_personas_marg").toInt(); 50 label_personas_spac = settings->value("label_personas_spac").toInt(); 51 52 frame_tiempos_x = settings->value("frame_tiempos_x").toInt(); 53 frame_tiempos_y = settings->value("frame_tiempos_y").toInt(); 54 frame_tiempos_w = settings->value("frame_tiempos_w").toInt(); 55 frame_tiempos_h = settings->value("frame_tiempos_h").toInt(); 56 frame_tiempos_marg = settings->value("frame_tiempos_marg").toInt(); 57 frame_tiempos_spac = settings->value("frame_tiempos_spac").toInt(); 49 49 Estudio comparativo de modelos de identificación facial basados en correlación 58 settings->endGroup(); 59 } void QConfig::EscribeTiemposModelos (int id_CSV) Funcion EscribeTiemposModelos. Escritura de los valores de los tiempos por creacion y carga. Escribe en un fichero los valores de los tiempos de creacion y carga de cada modelo utilizado en la aplicacion para un archivo CSV determinado. Parámetros: id_CSV Identificador del archivo CSV 101 { 102 //Apertura del fichero de escritura de los datos 103 QString nombre_fichero = QString("etc/Resultados/50x50/TiemposModelos_%1.m").arg(id_CSV); 104 settings = new QSettings(nombre_fichero, QSettings::IniFormat); 105 106 qDebug() << "Resultados: Guardando archivo " << nombre_fichero; 107 108 //Escritura de los datos en el fichero 109 settings->beginGroup(QString("TIEMPOS_MODELOS")); 110 for(uint i=0; i<seg_Modelos.size(); i++) 111 { 112 QString numero=QString("%1").arg(i+1); 113 QString linea=QString("%1 %2").arg((seg_Modelos[i]+seg_CSV), 0, 'f', 2).arg(seg_Carga[i],0,'f',2); 114 settings->setValue(numero, linea); 115 } 116 settings->endGroup(); 117 } void QConfig::EscribeValoresHombre (int id_modelo, int id_CSV) Funcion EscribeValoresHombre. Escritura de los valores de identificacion de sujetos masculinos. Escribe en un fichero los valores de identificacion de la base de datos de los sujetos masculinos generados por un modelo y archivo CSV especificos. Parámetros: id_modelo Identificador del modelo que ha generado los datos id_CSV Identificador del archivo CSV 82 { 83 //Apertura del fichero de escritura de los datos 84 QString nombre_fichero = QString("etc/Resultados/50x50/ResultadosHombreM3_%1%2.m").arg(id_CSV).arg(id_modelo); 85 settings = new QSettings(nombre_fichero, QSettings::IniFormat); 86 87 qDebug() << "Resultados: Guardando archivo " << nombre_fichero; 88 89 //Escritura de los datos en el fichero 90 settings->beginGroup(QString("IDENTIFICACION_HOMBRE")); 91 for(uint i=0; i<media_segundos.size(); i++) 92 { 93 QString numero=QString("%1").arg(i+1); 94 QString linea=QString("%1 %2 %3").arg(media_segundos[i], 0, 'f', 3).arg(confidence[i],0,'f',4).arg(prediccion[i]+1); 95 settings->setValue(numero, linea); 96 } 97 settings->endGroup(); 98 } void QConfig::EscribeValoresMujer (int id_modelo, int id_CSV) Funcion EscribeValoresMujer. Escritura de los valores de identificacion de sujetos femeninos. Escribe en un fichero los valores de identificacion de la base de datos de los sujetos femeninos generados por un modelo y archivo CSV especificos. Parámetros: id_modelo Identificador del modelo que ha generado los datos Anexo A. Documentación del código (Doxygen) 50 50 id_CSV Identificador del archivo CSV 63 { 64 //Apertura del fichero de escritura de los datos 65 QString nombre_fichero = QString("etc/Resultados/50x50/ResultadosMujerM3_%1%2.m").arg(id_CSV).arg(id_modelo); 66 settings = new QSettings(nombre_fichero, QSettings::IniFormat); 67 68 qDebug() << "Resultados: Guardando archivo " << nombre_fichero; 69 70 //Escritura de los datos en el fichero 71 settings->beginGroup(QString("IDENTIFICACION_MUJER")); 72 for(uint i=0; i<media_segundos.size(); i++) 73 { 74 QString numero=QString("%1").arg(i+1); 75 QString linea=QString("%1 %2 %3").arg(media_segundos[i], 0, 'f', 3).arg(confidence[i],0,'f',4).arg(prediccion[i]+1); 76 settings->setValue(numero, linea); 77 } 78 settings->endGroup(); 79 } void QConfig::Inicializar () Funcion Inicializar. Llama a CargarArchivo(); 24 { 25 CargarArchivo(0); 26 } Documentación de los datos miembro QString QConfig::background Contiene el nombre de la imagen de background. vector<float> QConfig::confidence Confianza de la identificacion. int QConfig::frame_tiempos_h Alto del recuadro de tiempos de identificacion. int QConfig::frame_tiempos_marg Margen del recuadro de tiempos de identificacion. int QConfig::frame_tiempos_spac Espaciado del recuadro de tiempos de identificacion. int QConfig::frame_tiempos_w Ancho del recuadro de tiempos de identificacion. int QConfig::frame_tiempos_x Posicion x en la pantalla para el recuadro de tiempos de identificacion. int QConfig::frame_tiempos_y Posicion y en la pantalla para el recuadro de tiempos de identificacion. int QConfig::label_personas_h Alto del recuadro para el numero de sujetos identificados. 51 51 Estudio comparativo de modelos de identificación facial basados en correlación int QConfig::label_personas_marg Margen del recuadro para el numero de sujetos identificados. int QConfig::label_personas_spac Espaciado del recuadro para el numero de sujetos identificados. int QConfig::label_personas_w Ancho del recuadro para el numero de sujetos identificados. int QConfig::label_personas_x Posicion x en la pantalla para el numero de sujetos identificados. int QConfig::label_personas_y Posicion y en la pantalla para el numero de sujetos identificados. vector<float> QConfig::media_segundos Tiempos de identificacion. vector<int> QConfig::prediccion Prediccion realizada por el modelo de identificacion. int QConfig::resolucion_h Resolucion de la pantalla en alto. int QConfig::resolucion_w Resolucion de la pantalla en ancho. vector<float> QConfig::seg_Carga Tiempos de carga de los distintos modelos de identificacion. float QConfig::seg_CSV Tiempo de carga del archivo CSV. vector<float> QConfig::seg_Modelos Tiempos de creacion de los distintos modelos de identificacion. QSettings* QConfig::settings[private] Utilizada para la lectura y escritura de ficheros La documentación para esta clase fue generada a partir de los siguientes ficheros:  src/Config.h  src/Config.cpp Anexo A. Documentación del código (Doxygen) 52 52 Referencia de la Clase QFormPrincipal Hereda de QWidget. Se encarga de gestionar la interfaz del programa. #include <FormPrincipal.h> Diagrama de herencias de QFormPrincipal Diagrama de colaboración para QFormPrincipal: Slots públicos  void SlotIniciar () Funcion SlotIniciar. Pone visibles los componentes de la interfaz de la aplicacion.  void SlotFinAperturaCSV () Funcion SlotFinAperturaCSV. Indica la creacion del primer modelo identificador.  void SlotActualizarTimer3 () Funcion SlotActualizarTimer3.  void SlotSiguienteModelo () Funcion SlotSiguienteModelo. Indica la creacion del siguente modelo identificador.  void SlotCargaModelo () Funcion SlotCargaModelo. Indica la carga del modelo que se va a utilizar en las identificaciones.  void SlotFinCargaModelo () Funcion SlotFinCargaModelo. Indica el fin de la carga del modelo que se va a utilizar.  void SlotCargaImagen () Funcion SlotCargaImagen. Carga la imagen a identificar.  void SlotActualizarTimer2 () Funcion SlotActualizarTimer2.  void SlotNuevaIdentificacion (float conf, int predLabel) Funcion SlotNuevaIdentificacion. Actualiza los valores producidos por la identificacion. Señales  void SignalAperturaCSV (QString fn_csv) Señal SignalAperturaCSV.  void SignalCreaModeloFisherFace (QString fn_model) Señal SignalCreaModeloFisherFace. 53 53 Estudio comparativo de modelos de identificación facial basados en correlación  void SignalCreaModeloEigenFace (QString fn_model) Señal SignalCreaModeloEigenFace.  void SignalCreaModeloLBPHFace (QString fn_model) Señal SignalCreaModeloLBPHFace.  void SignalCreaArbolFisherFace (QString fn_model, int id_CSV) Señal SignalCreaArbolFisherFace.  void SignalCreaArbolEigenFace (QString fn_model, int id_CSV) Señal SignalCreaArbolEigenFace.  void SignalCreaArbolLBPHFace (QString fn_model, int id_CSV) Señal SignalCreaArbolLBPHFace.  void SignalCargaModeloFisherFace (QString fn_model) Señal SignalCargaModeloFisherFace.  void SignalCargaModeloEigenFace (QString fn_model) Señal SignalCargaModeloEigenFace.  void SignalCargaModeloLBPHFace (QString fn_model) Señal SignalCargaModeloLBPHFace.  void SignalCargaArbolFisherFace (QString fn_model, int id_CSV) Señal SignalCargaArbolFisherFace.  void SignalCargaArbolEigenFace (QString fn_model, int id_CSV) Señal SignalCargaArbolEigenFace.  void SignalCargaArbolLBPHFace (QString fn_model, int id_CSV) Señal SignalCargaArbolLBPHFace.  void SignalIdentificar (Mat *test_im) Señal SignalIdentificar.  void SignalIdentificarArbol (Mat *test_im) Señal SignalIdentificarArbol. Métodos públicos  QFormPrincipal (QWidget *parent=0) Constructor de la clase QFormPrincipal.  ~QFormPrincipal () Destructor de la clase QFormPrincipal.  void SetupUI () Funcion SetupUI. Se encarga de la inicializacion de la interfaz de la aplicacion.  void Comenzar () Funcion Comenzar.  void keyPressEvent (QKeyEvent *e) Funcion keyPressEvent. Gestor de eventos de teclado. Atributos públicos  QFrame * frame_general  QLabel * label_fondo  QLabel * label_imagen  QLabel * label_num_personas  QFrame * frame_tiempos  QVBoxLayout * layout_tiempos  QLabel * label_text_tiempo_iden  QLabel * label_text_tiempo_med  QTimer * timer  QTimer * timer2  QTimer * timer3  QProceso * proceso Anexo A. Documentación del código (Doxygen) 54 54  QThread * thread Métodos privados  void ActualizarMedia () Funcion ActualizarMedia. Actualiza el valor de tiempo medio de identificacion. Atributos privados  float segundos  float seg_CSV  vector< string > nom_Modelos  int id_modelo  vector< float > seg_Modelos  vector< float > seg_Carga  int id_persona  int tam  Mat test_im  Mat * identifica  float med_seg  vector< float > media_segundos  vector< float > confidence  vector< int > prediccion  int id_CSV  bool genero  int num_personas Descripción detallada Hereda de QWidget. Se encarga de gestionar la interfaz del programa. Documentación del constructor y destructor QFormPrincipal::QFormPrincipal (QWidget * parent = 0) Constructor de la clase QFormPrincipal. Inicializa los valores por defecto de las variables de la clase. Inicializa la interfaz de la aplicacion. Conecta los temporizadores y los hilos entre si. Parámetros: parent Valor por defecto cero. Referencia a la clase padre. 14 : QWidget(parent) 15 { 16 //Inicializacion de valores 17 segundos=0; 18 id_modelo=0; 19 id_persona=1; 20 tam=50; 21 id_CSV=0; 22 genero=true; 23 med_seg=0; 24 num_personas=0; 25 26 //Inicializacion de la interfaz 27 SetupUI(); 28 29 //Inicializacion de los temporizadores 30 timer = new QTimer(this); 31 timer2 = new QTimer(this); 32 timer3 = new QTimer(this); 33 proceso = new QProceso(); 55 55 Estudio comparativo de modelos de identificación facial basados en correlación 34 35 //Inicializacion del hilo proceso 36 thread = new QThread(); 37 proceso->moveToThread(thread); 38 39 //Conexion de las señales emitidas por este hilo y el hilo proceso con las funciones a ejecutar 40 //Apertura del archivo CSV 41 connect(this, SIGNAL(SignalAperturaCSV(QString)), proceso, SLOT(SlotAbrirCSV(QString))); 42 connect(proceso, SIGNAL(SignalFinAperturaCSV()), this, SLOT(SlotFinAperturaCSV())); 43 44 //Creacion de los diferentes modelos 45 connect(this, SIGNAL(SignalCreaModeloFisherFace(QString)), proceso, SLOT(SlotCreaModeloFisherFace(QString))); 46 connect(this, SIGNAL(SignalCreaModeloEigenFace(QString)), proceso, SLOT(SlotCreaModeloEigenFace(QString))); 47 connect(this, SIGNAL(SignalCreaModeloLBPHFace(QString)), proceso, SLOT(SlotCreaModeloLBPHFace(QString))); 48 connect(this, SIGNAL(SignalCreaArbolFisherFace(QString, int)), proceso, SLOT(SlotCreaArbolFisherFace(QString, int))); 49 connect(this, SIGNAL(SignalCreaArbolEigenFace(QString, int)), proceso, SLOT(SlotCreaArbolEigenFace(QString, int))); 50 connect(this, SIGNAL(SignalCreaArbolLBPHFace(QString, int)), proceso, SLOT(SlotCreaArbolLBPHFace(QString, int))); 51 connect(proceso, SIGNAL(SignalFinCreacionModelo()), this, SLOT(SlotSiguienteModelo())); 52 53 //Carga de los diferentes modelos 54 connect(this, SIGNAL(SignalCargaModeloFisherFace(QString)), proceso, SLOT(SlotCargaModeloFisherFace(QString))); 55 connect(this, SIGNAL(SignalCargaModeloEigenFace(QString)), proceso, SLOT(SlotCargaModeloEigenFace(QString))); 56 connect(this, SIGNAL(SignalCargaModeloLBPHFace(QString)), proceso, SLOT(SlotCargaModeloLBPHFace(QString))); 57 connect(this, SIGNAL(SignalCargaArbolFisherFace(QString, int)), proceso, SLOT(SlotCargaArbolFisherFace(QString, int))); 58 connect(this, SIGNAL(SignalCargaArbolEigenFace(QString, int)), proceso, SLOT(SlotCargaArbolEigenFace(QString, int))); 59 connect(this, SIGNAL(SignalCargaArbolLBPHFace(QString, int)), proceso, SLOT(SlotCargaArbolLBPHFace(QString, int))); 60 connect(proceso, SIGNAL(SignalFinCargaModelo()), this, SLOT(SlotFinCargaModelo())); 61 62 //Identificacion de un sujeto 63 connect(this, SIGNAL(SignalIdentificar(Mat *)), proceso, SLOT(SlotIdentificar(Mat *))); 64 connect(this, SIGNAL(SignalIdentificarArbol(Mat *)), proceso, SLOT(SlotIdentificarArbol(Mat *))); 65 connect(proceso, SIGNAL(SignalFinIdentificacion(float, int)), this, SLOT(SlotNuevaIdentificacion(float, int))); 66 67 //Conexion de las señales emitidas por los temporizadores con las funciones a ejecutar de este hilo 68 connect(timer, SIGNAL(timeout()), this, SLOT(SlotTerminar())); 69 connect(timer2, SIGNAL(timeout()), this, SLOT(SlotActualizarTimer2())); 70 connect(timer3, SIGNAL(timeout()), this, SLOT(SlotActualizarTimer3())); 71 72 } QFormPrincipal::~QFormPrincipal () Destructor de la clase QFormPrincipal. Elimina la variable proceso. 146 { 147 delete proceso; 148 } Anexo A. Documentación del código (Doxygen) 62 62 302 //Emision de señal para cargar el modelo FisherFace 303 emit SignalCargaModeloFisherFace(QString::fromStdString(nom_Modelos[id_modelo])); 304 } 305 else if(id_modelo==1) 306 { 307 //Temporizador activado 308 timer3->start(10); 309 310 //Emision de señal para cargar el modelo EigenFace 311 emit SignalCargaModeloEigenFace(QString::fromStdString(nom_Modelos[id_modelo])); 312 } 313 else if(id_modelo==2) 314 { 315 //Temporizador activado 316 timer3->start(10); 317 318 //Emision de señal para cargar el modelo LBPHFace 319 emit SignalCargaModeloLBPHFace(QString::fromStdString(nom_Modelos[id_modelo])); 320 } 321 else if(id_modelo==3) 322 { 323 //Temporizador activado 324 timer3->start(10); 325 326 //Emision de señal para cargar el modelo FisherFace con estructura en arbol 327 emit SignalCargaArbolFisherFace(QString::fromStdString(nom_Modelos[id_modelo]), id_CSV); 328 } 329 else if(id_modelo==4) 330 { 331 //Temporizador activado 332 timer3->start(10); 333 334 //Emision de señal para cargar el modelo EigenFace con estructura en arbol 335 emit SignalCargaArbolEigenFace(QString::fromStdString(nom_Modelos[id_modelo]), id_CSV); 336 } 337 else if(id_modelo==5) 338 { 339 //Temporizador activado 340 timer3->start(10); 341 342 //Emision de señal para cargar el modelo LBPHFace con estructura en arbol 343 emit SignalCargaArbolLBPHFace(QString::fromStdString(nom_Modelos[id_modelo]), id_CSV); 344 } 345 } void QFormPrincipal::SlotFinAperturaCSV ()[slot] Funcion SlotFinAperturaCSV. Indica la creacion del primer modelo identificador. Una vez cargadas las imagenes utilizadas por los modelos identificadores, se para el temporizador timer3 y se guarda el resultado. Se reinicializa el temporizador y se indica que comience la creacion del primer modelo de identificacion. 184 { 185 //Detencion del temporizador 186 timer3->stop(); 187 188 //Asociacion de los segundos que se ha tardado en cargar el archivo CSV 189 seg_CSV=segundos; 190 191 //Emision de la señal para la creacion del modelo de identificacion FisherFace 192 nom_Modelos.push_back("etc/Resultados/50x50/FisherFace_4.yml"); 193 segundos=0; 194 timer3->start(10); 195 emit SignalCreaModeloFisherFace(QString::fromStdString(nom_Modelos[id_modelo])); 196 } void QFormPrincipal::SlotFinCargaModelo ()[slot] Funcion SlotFinCargaModelo. Indica el fin de la carga del modelo que se va a utilizar. 63 63 Estudio comparativo de modelos de identificación facial basados en correlación Terminada la carga del modelo de identificacion, se para el temporizador timer3 y se guarda el tiempo de carga del modelo. Se cambia la imagen de fondo y llama a SlotCargaImagen(). 348 { 349 //Detencion temporizador 350 timer3->stop(); 351 352 //Asociacion de los segundos que se ha tardado en crear el modelo 353 seg_Carga.push_back(segundos); 354 segundos=0; 355 356 //Carga nueva imagen de fondo 357 QPixmap pixmap_imagen= QPixmap(QString("resources/media/imagen2")); 358 label_imagen->setPixmap(pixmap_imagen); 359 label_imagen->setMask(pixmap_imagen.mask()); 360 361 //Comienzo de la identificacion 362 SlotCargaImagen(); 363 } void QFormPrincipal::SlotIniciar ()[slot] Funcion SlotIniciar. Pone visibles los componentes de la interfaz de la aplicacion. Comienzo del hilo thread. Los componentes de la interfaz de la aplicacion se hacen visibles. Comienzo del temporizador timer3. Da comienzo a la carga de las imagenes utilizadas para crear los distintos modelos de identificacion. 156 { 157 //Comienzo del hilo thread 158 thread->start(); 159 160 //Objetos de la interfaz de la aplicacion visibles 161 label_imagen-> setVisible(true); 162 label_fondo-> setVisible(true); 163 label_num_personas-> setVisible(true); 164 frame_tiempos-> setVisible(true); 165 166 //Valores iniciales de sujetos identificados y tiempos 167 label_num_personas->setText(QString("%1").arg(num_personas)); 168 label_text_tiempo_iden->setText(QString("%1").arg(segundos, 0, 'f', 3)); 169 label_text_tiempo_med->setText(QString("%1").arg(med_seg, 0, 'f', 3)); 170 171 //Temporizador activado 172 timer3->start(10); 173 174 //Emision de la señal para proceder a la apertura del archivo CSV 175 emit SignalAperturaCSV("resources/media/CSV0.txt"); 176 } void QFormPrincipal::SlotNuevaIdentificacion (float conf, int predLabel)[slot] Funcion SlotNuevaIdentificacion. Actualiza los valores producidos por la identificacion. Terminada la identificacion actual, se detiene el temporizador timer2, se actualizan los valores correspondientes a una identificacion y se llama a SlotCargaImagen() para proceder a la carga de la siguiente imagen a identificar. Parámetros: conf El valor de confianza devuelto por el modelo tras la identificacion predLabel El valor de la prediccion del sujeto que se ha identificado. 473 { 474 //Detencion del temporizador de identificacion 475 timer2->stop(); 476 477 //Asociacion de los nuevos datos generados por la identificacion 478 confidence.push_back(conf); 479 prediccion.push_back(predLabel); 480 num_personas++; 481 ActualizarMedia(); 482 segundos=0; 483 484 //Actualizacion en la interfaz del numero de personas identificadas 485 label_num_personas->setText(QString("%1").arg(num_personas)); Anexo A. Documentación del código (Doxygen) 64 64 486 487 //Actualizacion en la interfaz del tiempo de identificacion para la proxima identificacion 488 label_text_tiempo_iden->setText(QString("%1").arg(segundos, 0, 'f', 3)); 489 490 //Siguiente identificacion 491 SlotCargaImagen(); 492 } void QFormPrincipal::SlotSalir ()[slot] Funcion SlotSalir. Guarda los tiempos de creacion y carga de los modelos de identificacion. Cambia la imagen de fondo. Se guardan los tiempos de creacion y carga de los diferentes modelos de identificacion empleados. Se inicializa el temporizador timer1. 510 { 511 //Carga nueva imagen de fondo 512 QPixmap pixmap_imagen= QPixmap(QString("resources/media/imagen3")); 513 label_imagen->setPixmap(pixmap_imagen); 514 label_imagen->setMask(pixmap_imagen.mask()); 515 516 //Escritura de los tiempos de creacion y carga de los modelos de identificacion empleados 517 config.seg_CSV=this->seg_CSV; 518 config.seg_Modelos=this->seg_Modelos; 519 config.seg_Carga=this->seg_Carga; 520 config.EscribeTiemposModelos(id_CSV); 521 522 //Activacion temporizador final 523 timer->start(500); 524 } void QFormPrincipal::SlotSiguienteModelo ()[slot] Funcion SlotSiguienteModelo. Indica la creacion del siguente modelo identificador. Terminada la creacion del modelo identificador, se para el temporizador timer3 y se guarda el tiempo de creacion del modelo. Se reinicializa el temporizador y se indica que comience la creacion del siguiente modelo de identificacion. Se repite hasta que se hayan creado los seis modelos diferentes. 199 { 200 if(id_modelo==0) 201 { 202 //Detencion del temporizador 203 timer3->stop(); 204 205 //Asociacion de los segundos que se ha tardado en crear el modelo 206 seg_Modelos.push_back(segundos); 207 segundos=0; 208 id_modelo=1; 209 210 //Emision de la señal para la creacion del modelo de identificacion EigenFace 211 nom_Modelos.push_back("etc/Resultados/50x50/EigenFace_4.yml"); 212 timer3->start(10); 213 emit SignalCreaModeloEigenFace(QString::fromStdString(nom_Modelos[id_modelo])); 214 } 215 else if(id_modelo==1) 216 { 217 //Detencion del temporizador 218 timer3->stop(); 219 220 //Asociacion de los segundos que se ha tardado en crear el modelo 221 seg_Modelos.push_back(segundos); 222 segundos=0; 223 id_modelo=2; 224 225 //Emision de la señal para la creacion del modelo de identificacion LBPHFace 226 nom_Modelos.push_back("etc/Resultados/50x50/LBPHFace_4.yml"); 227 timer3->start(10); 228 emit SignalCreaModeloLBPHFace(QString::fromStdString(nom_Modelos[id_modelo])); 229 } 230 else if(id_modelo==2) 231 { 65 65 Estudio comparativo de modelos de identificación facial basados en correlación 232 //Detencion del temporizador 233 timer3->stop(); 234 235 //Asociacion de los segundos que se ha tardado en crear el modelo 236 seg_Modelos.push_back(segundos); 237 segundos=0; 238 239 //Emision de la señal para la creacion del modelo de identificacion FisherFace con estructura en arbol. 240 nom_Modelos.push_back("etc/Resultados/50x50/Arbol/FisherFace_%d%d.yml"); 241 id_modelo=3; 242 timer3->start(10); 243 emit SignalCreaArbolFisherFace(QString::fromStdString(nom_Modelos[id_modelo]), id_CSV); 244 } 245 else if(id_modelo==3) 246 { 247 //Detencion del temporizador 248 timer3->stop(); 249 250 //Asociacion de los segundos que se ha tardado en crear el modelo 251 seg_Modelos.push_back(segundos); 252 segundos=0; 253 id_modelo=4; 254 255 //Emision de la señal para la creacion del modelo de identificacion EigenFace con estructura en arbol. 256 nom_Modelos.push_back("etc/Resultados/50x50/Arbol/EigenFace_%d%d.yml"); 257 timer3->start(10); 258 emit SignalCreaArbolEigenFace(QString::fromStdString(nom_Modelos[id_modelo]), id_CSV); 259 } 260 else if(id_modelo==4) 261 { 262 //Detencion del temporizador 263 timer3->stop(); 264 265 //Asociacion de los segundos que se ha tardado en crear el modelo 266 seg_Modelos.push_back(segundos); 267 segundos=0; 268 id_modelo=5; 269 270 //Emision de la señal para la creacion del modelo de identificacion LBPHFace con estructura en arbol. 271 nom_Modelos.push_back("etc/Resultados/50x50/Arbol/LBPHFace_%d%d.yml"); 272 timer3->start(10); 273 emit SignalCreaArbolLBPHFace(QString::fromStdString(nom_Modelos[id_modelo]), id_CSV); 274 } 275 else if(id_modelo==5) 276 { 277 //Detencion del temporizador 278 timer3->stop(); 279 280 //Asociacion de los segundos que se ha tardado en crear el modelo 281 seg_Modelos.push_back(segundos); 282 segundos=0; 283 id_modelo=0; 284 285 //Carga del primer modelo 286 SlotCargaModelo(); 287 } 288 } void QFormPrincipal::SlotTerminar ()[slot] Funcion SlotTerminar. Cierra la clase actual 527 { 528 this->close(); 529 } Anexo A. Documentación del código (Doxygen) 66 66 Documentación de los datos miembro vector<float> QFormPrincipal::confidence[private] Valores de confianza de las identificaciones realizadas QFrame* QFormPrincipal::frame_general Espacio reservado para la interfaz de la aplicacion. QFrame* QFormPrincipal::frame_tiempos Espacio reservado para la informacion de tiempos. bool QFormPrincipal::genero[private] Genero sobre el que se esta identificando int QFormPrincipal::id_CSV[private] Identificador del archivo CSV int QFormPrincipal::id_modelo[private] Identificador para el modelo que se este usando int QFormPrincipal::id_persona[private] Identificador para cargar el sujeto a identificar Mat* QFormPrincipal::identifica[private] Utilizado para transferir la imagen del sujeto a identificar a la clase QProceso QLabel* QFormPrincipal::label_fondo Carga la imagen de background de la aplicacion. QLabel* QFormPrincipal::label_imagen Carga las imagenes de fondo que apareceran a lo largo de la aplicacion. QLabel* QFormPrincipal::label_num_personas Se encarga de actualizar el valor del numero de identificaciones realizadas. QLabel* QFormPrincipal::label_text_tiempo_iden Se encarga de actualizar el valor de tiempo empleado en la identificacion. QLabel* QFormPrincipal::label_text_tiempo_med Se encarga de acutalizar el valor de tiempo medio de las identificaciones. QVBoxLayout* QFormPrincipal::layout_tiempos Se encarga del layout de la informacion de tiempos. float QFormPrincipal::med_seg[private] Media del tiempo empleado en las identificaciones vector<float> QFormPrincipal::media_segundos[private] Tiempos empleados en las distintas identificaciones realizadas vector<string> QFormPrincipal::nom_Modelos[private] Nombres utilizados para guardar los distintos modelos de identificacion 67 67 Estudio comparativo de modelos de identificación facial basados en correlación int QFormPrincipal::num_personas[private] Numero total de personas identificadas vector<int> QFormPrincipal::prediccion[private] Valores de prediccion de las identificaciones realizadas QProceso* QFormPrincipal::proceso Instancia de la clase QProceso. vector<float> QFormPrincipal::seg_Carga[private] Tiempos empleados para la carga de los diferentes modelos de identificacion float QFormPrincipal::seg_CSV[private] Guarda el tiempo que se tarda en abir el archivo CSV vector<float> QFormPrincipal::seg_Modelos[private] Tiempos empleados para la creacion de los diferentes modelos de identificacion float QFormPrincipal::segundos[private] Usada por los temporizadores int QFormPrincipal::tam[private] Tamaño de la base de datos de sujetos a identificar Mat QFormPrincipal::test_im[private] Imagen del sujeto a identificar QThread* QFormPrincipal::thread Instancia de la clase QThread. QTimer* QFormPrincipal::timer Temporizador para la finalizacion de la aplicacion. QTimer* QFormPrincipal::timer2 Temporizador para obtener los tiempos de identificacion. QTimer* QFormPrincipal::timer3 Temporizador para obtener los tiempo de creacion y carga de los diferentes modelos. La documentación para esta clase fue generada a partir de los siguientes ficheros:  src/FormPrincipal.h  src/FormPrincipal.cpp Anexo A. Documentación del código (Doxygen) 68 68 Referencia de la Clase QProceso Hereda de QObject. Se encarga de la creacion, carga e identificacion llevada a cabo por los modelos. #include <Proceso.h> Diagrama de herencias de QProceso Diagrama de colaboración para QProceso: Slots públicos  void SlotAbrirCSV (QString fn_csv) Funcion SlotAbrirCSV. Indica cuando se ha terminado la lectura del fichero CSV.  void SlotCreaModeloFisherFace (QString fn_model) Funcion SlotCreaModeloFisherFace. Crea el modelo FisherFace.  void SlotCreaModeloEigenFace (QString fn_model) Funcion SlotCreaModeloEigenFace. Crea el modelo EigenFace.  void SlotCreaModeloLBPHFace (QString fn_model) Funcion SlotCreaModeloLBPHFace. Crea el modelo LBPHFace.  void SlotCargaModeloFisherFace (QString fn_model) Funcion SlotCargaModeloFisherFace. Carga el modelo FisherFace.  void SlotCargaModeloEigenFace (QString fn_model) Funcion SlotCargaModeloEigenFace. Carga el modelo EigenFace.  void SlotCargaModeloLBPHFace (QString fn_model) Funcion SlotCargaModeloLBPHFace. Carga el modelo LBPHFace.  void SlotIdentificar (Mat *test_im) Funcion SlotIdentificar. Identifica a un sujeto.  void SlotCreaArbolFisherFace (QString fn_model, int id_CSV) Funcion SlotCreaArbolFisherFace. Crea el modelo FisherFace con estructura en arbol.  void SlotCreaArbolEigenFace (QString fn_model, int id_CSV) Funcion SlotCreaArbolEigenFace. Crea el modelo EigenFace con estructura en arbol.  void SlotCreaArbolLBPHFace (QString fn_model, int id_CSV) Funcion SlotCreaArbolLBPHFace. Crea el modelo LBPHFace con estructura en arbol.  void SlotCargaArbolFisherFace (QString fn_model, int id_CSV) Funcion SlotCargaArbolFisherFace. Carga el modelo FisherFace con estructura en arbol.  void SlotCargaArbolEigenFace (QString fn_model, int id_CSV) Funcion SlotCargaArbolEigenFace. Carga el modelo EigenFace con estructura en arbol.  void SlotCargaArbolLBPHFace (QString fn_model, int id_CSV) Funcion SlotCargaArbolLBPHFace. Carga el modelo LBPHFace con estructura en arbol.  void SlotIdentificarArbol (Mat *test_im) 69 69 Estudio comparativo de modelos de identificación facial basados en correlación Funcion SlotIdentificar. Identifica a un sujeto con un modelo con estructura en arbol. Señales  void SignalFinAperturaCSV () Señal SignalFinAperturaCSV.  void SignalFinCreacionModelo () Señal SignalFinCreacionModelo.  void SignalFinCargaModelo () Señal SignalFinCargaModelo.  void SignalFinIdentificacion (float conf, int predLabel) Señal SignalFinIdentificacion. Métodos públicos  QProceso () Constructor de la clase QProceso.  virtual ~QProceso () Destructor de la clase QProceso. Métodos privados  void read_csv (const string &filename, vector< Mat > &images, vector< int > &labels, char separator) Funcion read_csv. Lectura del archivo CSV. Atributos privados  vector< Mat > images  vector< Mat > im_arbol  Mat transicion  vector< int > labels  Ptr< FaceRecognizer > model  vector< Ptr< FaceRecognizer > > arbol  vector< int > posiciones  int num_saltos2  int num_saltos5  int num_images  int num_modelos  int im_size  int tam_posiciones  int predictedLabel  int predictedLabelArbol  int prox_model  double confidence  ofstream ficheroArbol  ifstream ficheroArbolLec  bool fin Descripción detallada Hereda de QObject. Se encarga de la creacion, carga e identificacion llevada a cabo por los modelos. Documentación del constructor y destructor QProceso::QProceso () Constructor de la clase QProceso. Anexo A. Documentación del código (Doxygen) 70 70 Constructor vacio. 14 { 15 16 } QProceso::~QProceso ()[virtual] Destructor de la clase QProceso. Libera la memoria reservada por images. 19 { 20 images.clear(); 21 } Documentación de las funciones miembro void QProceso::read_csv (const string & filename, vector< Mat > & images, vector< int > & labels, char separator)[private] Funcion read_csv. Lectura del archivo CSV. Carga de las imagenes utilizadas para la creacion del modelo, asi como las relacion de las imagenes con las clases realizando la lectura de un fichero CSV. Parámetros: filename Nombre del fichero CSV. images Vector en el que se cargaran las imagenes. labels Vector en el que se cargara la relacion imagenes - clases del identificador. separator Caracter con el cual se separa el nombre de la imagen a cargar con la clase que la identifica. 23 { 24 25 //Apertura del fichero 26 std::ifstream file(filename.c_str(), std::ifstream::in); 27 if (!file) { 28 string error_message = "No valid input file was given, please check the given filename."; 29 CV_Error(CV_StsBadArg, error_message); 30 } 31 Mat cambio; 32 string line, path, classlabel; 33 //Lectura linea a linea 34 while (getline(file, line)) { 35 stringstream liness(line); 36 getline(liness, path, separator); 37 getline(liness, classlabel); 38 if(!path.empty() && !classlabel.empty()) { 39 //Apertura de la imagen 40 cambio=imread(path,0); 41 resize(cambio,cambio,Size(50,50)); 42 //Incorporacion de la imagen y la clase de identificacion correpondiente 43 images.push_back(cambio); 44 labels.push_back(atoi(classlabel.c_str())); 45 } 46 } 47 } void QProceso::SignalFinAperturaCSV ()[signal] Señal SignalFinAperturaCSV. Señal que indica que se ha finalizado la apertura del fichero CSV. void QProceso::SignalFinCargaModelo ()[signal] 71 71 Estudio comparativo de modelos de identificación facial basados en correlación Señal SignalFinCargaModelo. Señal que indica que se ha finalizado la carga de un modelo. void QProceso::SignalFinCreacionModelo ()[signal] Señal SignalFinCreacionModelo. Señal que indica que se ha finalizado la creacion de un modelo. void QProceso::SignalFinIdentificacion (float conf, int predLabel)[signal] Señal SignalFinCreacionIdentificacion. Señal que indica que se ha finalizado la identificacion de un sujeto. Parámetros: conf Confianza de la prediccion. predLabel Prediccion de la identificacion. void QProceso::SlotAbrirCSV (QString fn_csv)[slot] Funcion SlotAbrirCSV. Indica cuando se ha terminado la lectura del fichero CSV. Llama a la funcion read_csv(); Indica que se ha finalizado con la lectura y carga del fichero CSV. Parámetros: fn_csv Nombre del fichero CSV. 50 { 51 read_csv(fn_csv.toUtf8().constData(), images,labels,';'); 52 53 //Emision de la señal de fin de lectura del fichero CSV 54 emit SignalFinAperturaCSV(); 55 } void QProceso::SlotCargaArbolEigenFace (QString fn_model, int id_CSV)[slot] Funcion SlotCargaArbolEigenFace. Carga el modelo EigenFace con estructura en arbol. Carga el modelo EigenFace con estructura en arbol. Primero carga los modelos binarios. A continuacion, carga los modelos con cinco clases identificadoras. Una vez cargadas todas las ramas del arbol, se indica la finalizacion de la carga del arbol. Parámetros: fn_model Nombre con el cual se cargaran los modelos de las ramas de arbol. id_CSV Identificador del fichero CSV. 1570 { 1571 //Apertura y lectura de las caracteristicas del modelo con estructura en arbol 1572 string line; 1573 ficheroArbolLec.open(QString("etc/Resultados/50x50/ParamArbolEigenFace%1.txt").arg(id_CSV).to Utf8().constData()); 1574 getline(ficheroArbolLec,line); 1575 num_modelos=atoi(line.c_str()); 1576 getline(ficheroArbolLec,line); 1577 num_saltos2=atoi(line.c_str()); 1578 getline(ficheroArbolLec,line); 1579 num_saltos5=atoi(line.c_str()); 1580 ficheroArbolLec.close(); 1581 arbol.clear(); 1582 1583 //Carga de los modelos de cada rama que forma el arbol 1584 for(int i=0;i<num_modelos;i++) 1585 { 1586 model.release(); 1587 model=createEigenFaceRecognizer(); 1588 arbol.push_back(model); 1589 char intermedio[100]={0}; 1590 sprintf(intermedio,fn_model.toUtf8().constData(),id_CSV,i); 1591 arbol[i]->load(intermedio); Anexo A. Documentación del código (Doxygen) 78 78 910 num_modelos++; 911 im_arbol.clear(); 912 //Seleccion una imagen por clase 913 if(id_CSV%2==0) 914 { 915 for(int j=posiciones[5*i]+1;j<=posiciones[5*i+1];j++) 916 { 917 images[j].copyTo(transicion); 918 im_arbol.push_back(transicion); 919 transicion.release(); 920 } 921 } 922 //Seleccion dos imagenes por clase 923 else 924 { 925 for(int j=posiciones[5*i]+1;j<=posiciones[5*i+1];j++) 926 { 927 images[2*j].copyTo(transicion); 928 im_arbol.push_back(transicion); 929 transicion.release(); 930 images[2*j+1].copyTo(transicion); 931 im_arbol.push_back(transicion); 932 transicion.release(); 933 } 934 } 935 //Creacion del modelo de cinco clases identificadoras 936 model.release(); 937 model = createEigenFaceRecognizer(); 938 arbol.push_back(model); 939 arbol[num_modelos]->train(im_arbol,labels); 940 num_modelos++; 941 im_arbol.clear(); 942 //Seleccion una imagen por clase 943 if(id_CSV%2==0) 944 { 945 for(int j=posiciones[5*i+1]+1;j<=posiciones[5*i+2];j++) 946 { 947 images[j].copyTo(transicion); 948 im_arbol.push_back(transicion); 949 transicion.release(); 950 } 951 } 952 //Seleccion dos imagenes por clase 953 else 954 { 955 for(int j=posiciones[5*i+1]+1;j<=posiciones[5*i+2];j++) 956 { 957 images[2*j].copyTo(transicion); 958 im_arbol.push_back(transicion); 959 transicion.release(); 960 images[2*j+1].copyTo(transicion); 961 im_arbol.push_back(transicion); 962 transicion.release(); 963 } 964 } 965 //Creacion del modelo de cinco clases identificadoras 966 model.release(); 967 model = createEigenFaceRecognizer(); 968 arbol.push_back(model); 969 arbol[num_modelos]->train(im_arbol,labels); 970 num_modelos++; 971 im_arbol.clear(); 972 //Seleccion una imagen por clase 973 if(id_CSV%2==0) 974 { 975 for(int j=posiciones[5*i+2]+1;j<=posiciones[5*i+3];j++) 976 { 977 images[j].copyTo(transicion); 978 im_arbol.push_back(transicion); 979 transicion.release(); 980 } 981 } 982 //Seleccion dos imagenes por clase 983 else 984 { 985 for(int j=posiciones[5*i+2]+1;j<=posiciones[5*i+3];j++) 986 { 79 79 Estudio comparativo de modelos de identificación facial basados en correlación 987 images[2*j].copyTo(transicion); 988 im_arbol.push_back(transicion); 989 transicion.release(); 990 images[2*j+1].copyTo(transicion); 991 im_arbol.push_back(transicion); 992 transicion.release(); 993 } 994 } 995 //Creacion del modelo de cinco clases identificadoras 996 model.release(); 997 model = createEigenFaceRecognizer(); 998 arbol.push_back(model); 999 arbol[num_modelos]->train(im_arbol,labels); 1000 num_modelos++; 1001 im_arbol.clear(); 1002 //Seleccion una imagen por clase 1003 if(id_CSV%2==0) 1004 { 1005 for(int j=posiciones[5*i+3]+1;j<=posiciones[5*i+4];j++) 1006 { 1007 images[j].copyTo(transicion); 1008 im_arbol.push_back(transicion); 1009 transicion.release(); 1010 } 1011 } 1012 //Seleccion dos imagenes por clase 1013 else 1014 { 1015 for(int j=posiciones[5*i+3]+1;j<=posiciones[5*i+4];j++) 1016 { 1017 images[2*j].copyTo(transicion); 1018 im_arbol.push_back(transicion); 1019 transicion.release(); 1020 images[2*j+1].copyTo(transicion); 1021 im_arbol.push_back(transicion); 1022 transicion.release(); 1023 } 1024 } 1025 //Creacion del modelo de cinco clases identificadoras 1026 model.release(); 1027 model = createEigenFaceRecognizer(); 1028 arbol.push_back(model); 1029 arbol[num_modelos]->train(im_arbol,labels); 1030 num_modelos++; 1031 im_arbol.clear(); 1032 } 1033 //Tramos para los siguientes modelos 1034 tam_posiciones=posiciones.size(); 1035 for(int i=0;i<(tam_posiciones-1);i++) 1036 { 1037 if(i==0) 1038 { 1039 posiciones.push_back(((posiciones[0]+1)/5)-1); 1040 posiciones.push_back((2*(posiciones[0]+1)/5)-1); 1041 posiciones.push_back((3*(posiciones[0]+1)/5)-1); 1042 posiciones.push_back((4*(posiciones[0]+1)/5)-1); 1043 } 1044 posiciones.push_back(((posiciones[0]+1)/5)+posiciones[i]); 1045 posiciones.push_back((2*(posiciones[0]+1)/5)+posiciones[i]); 1046 posiciones.push_back((3*(posiciones[0]+1)/5)+posiciones[i]); 1047 posiciones.push_back((4*(posiciones[0]+1)/5)+posiciones[i]); 1048 } 1049 std::sort(posiciones.begin(),posiciones.end()); 1050 num_saltos5++; 1051 num_images/=5; 1052 } 1053 } 1054 1055 //Modelo arbol creado completo. Se procede a guardarlo 1056 for(uint i=0;i<arbol.size();i++) 1057 { 1058 char intermedio[100]={0}; 1059 sprintf(intermedio,fn_model.toUtf8().constData(),id_CSV,i); 1060 arbol[i]->save(intermedio); 1061 } 1062 arbol.clear(); 1063 char buf[40]={0}; 1064 sprintf( buf, "%d\n%d\n%d", num_modelos, num_saltos2, num_saltos5); Anexo A. Documentación del código (Doxygen) 80 80 1065 ficheroArbol.open(QString("etc/Resultados/50x50/ParamArbolEigenFace%1.txt").arg(id_CSV).toUtf 8().constData()); 1066 ficheroArbol<<buf; 1067 ficheroArbol.close(); 1068 posiciones.clear(); 1069 1070 //Emision de la señal de fin de creacion del modelo 1071 emit SignalFinCreacionModelo(); 1072 } void QProceso::SlotCreaArbolFisherFace (QString fn_model, int id_CSV)[slot] Funcion SlotCreaArbolFisherFace. Crea el modelo FisherFace con estructura en arbol. Crea el modelo FisherFace con estructura en arbol. Primero crea los modelos binarios. A continuacion, crea los modelos con cinco clases identificadoras. Una vez creadas todas las ramas del arbol, procede a guardar el arbol completo. Por ultimo, indica la finalizacion de la creacion del arbol. Parámetros: fn_model Nombre con el cual se guardaran las ramas de arbol. id_CSV Identificador del fichero CSV. 141 { 142 num_saltos2=0; 143 num_saltos5=0; 144 num_modelos=0; 145 146 //Decision de una imagen por clase o dos imagenes por clase 147 if(id_CSV%2!=0) 148 { 149 im_size=images.size()/2; 150 num_images=images.size()/2; 151 } 152 else 153 { 154 im_size=images.size(); 155 num_images=images.size(); 156 } 157 158 //Creacion de las ramas de modelo binario 159 while(num_images%2==0&&(int)posiciones.size()!=im_size) 160 { 161 //Relacion una imagen por clase 162 if(id_CSV%2==0) 163 { 164 labels.clear(); 165 for(int i=0;i<(num_images)/2;i++) 166 labels.push_back(0); 167 for(int i=0;i<(num_images)/2;i++) 168 labels.push_back(1); 169 } 170 //Relacion dos imagenes por clase 171 else 172 { 173 labels.clear(); 174 for(int i=0;i<(num_images)/2;i++) 175 { 176 labels.push_back(0); 177 labels.push_back(0); 178 } 179 for(int i=0;i<(num_images)/2;i++) 180 { 181 labels.push_back(1); 182 labels.push_back(1); 183 } 184 } 185 //Creacion del modelo mujer - hombre 186 if(num_saltos2==0) 187 { 188 model = createFisherFaceRecognizer(); 189 arbol.push_back(model); 190 arbol[num_modelos]->train(images,labels); 191 num_modelos++; 192 num_saltos2++; 81 81 Estudio comparativo de modelos de identificación facial basados en correlación 193 posiciones.push_back(im_size/2-1); 194 posiciones.push_back(im_size-1); 195 num_images/=2; 196 } 197 //Creacion del resto de ramas binarias 198 else 199 { 200 for(uint i=0;i<(posiciones.size()/2);i++) 201 { 202 //Seleccion una imagen por clase 203 if(id_CSV%2==0) 204 { 205 for(int j=(2*num_images*i);j<=posiciones[2*i];j++) 206 { 207 images[j].copyTo(transicion); 208 im_arbol.push_back(transicion); 209 transicion.release(); 210 } 211 } 212 //Seleccion dos imagenes por clase 213 else 214 { 215 for(int j=(2*num_images*i);j<=posiciones[2*i];j++) 216 { 217 images[2*j].copyTo(transicion); 218 im_arbol.push_back(transicion); 219 transicion.release(); 220 images[2*j+1].copyTo(transicion); 221 im_arbol.push_back(transicion); 222 transicion.release(); 223 } 224 } 225 //Creacion modelo binario 226 model.release(); 227 model = createFisherFaceRecognizer(); 228 arbol.push_back(model); 229 arbol[num_modelos]->train(im_arbol,labels); 230 num_modelos++; 231 im_arbol.clear(); 232 //Seleccion una imagen por clase 233 if(id_CSV%2==0) 234 { 235 for(int j=posiciones[2*i]+1;j<=posiciones[2*i+1];j++) 236 { 237 images[j].copyTo(transicion); 238 im_arbol.push_back(transicion); 239 transicion.release(); 240 } 241 } 242 //Seleccion dos imagenes por clase 243 else 244 { 245 for(int j=posiciones[2*i]+1;j<=posiciones[2*i+1];j++) 246 { 247 images[2*j].copyTo(transicion); 248 im_arbol.push_back(transicion); 249 transicion.release(); 250 images[2*j+1].copyTo(transicion); 251 im_arbol.push_back(transicion); 252 transicion.release(); 253 } 254 } 255 //Creacion modelo binario 256 model.release(); 257 model = createFisherFaceRecognizer(); 258 arbol.push_back(model); 259 arbol[num_modelos]->train(im_arbol,labels); 260 num_modelos++; 261 im_arbol.clear(); 262 } 263 //Tramos para los siguientes modelos 264 tam_posiciones=posiciones.size(); 265 for(int i=0;i<(tam_posiciones/2);i++) 266 { 267 posiciones.push_back(((posiciones[2*i]+1)/2)-1); 268 posiciones.push_back(posiciones[tam_posiciones+2*i]+num_images); 269 } 270 std::sort(posiciones.begin(),posiciones.end()); 271 num_saltos2++; Anexo A. Documentación del código (Doxygen) 82 82 272 num_images/=2; 273 } 274 } 275 276 //Creacion de las ramas de modelo con cinco clases identificadoras 277 while(num_images%5==0&&(int)posiciones.size()!=im_size) 278 { 279 //Relacion una imagen por clase 280 if(id_CSV%2==0) 281 { 282 labels.clear(); 283 for(int i=0;i<(num_images)/5;i++) 284 labels.push_back(0); 285 for(int i=0;i<(num_images)/5;i++) 286 labels.push_back(1); 287 for(int i=0;i<(num_images)/5;i++) 288 labels.push_back(2); 289 for(int i=0;i<(num_images)/5;i++) 290 labels.push_back(3); 291 for(int i=0;i<(num_images)/5;i++) 292 labels.push_back(4); 293 } 294 //Relacion dos imagenes por clase 295 else 296 { 297 labels.clear(); 298 for(int i=0;i<(num_images)/5;i++) 299 { 300 labels.push_back(0); 301 labels.push_back(0); 302 } 303 for(int i=0;i<(num_images)/5;i++) 304 { 305 labels.push_back(1); 306 labels.push_back(1); 307 } 308 for(int i=0;i<(num_images)/5;i++) 309 { 310 labels.push_back(2); 311 labels.push_back(2); 312 } 313 for(int i=0;i<(num_images)/5;i++) 314 { 315 labels.push_back(3); 316 labels.push_back(3); 317 } 318 for(int i=0;i<(num_images)/5;i++) 319 { 320 labels.push_back(4); 321 labels.push_back(4); 322 } 323 } 324 //Creacion de los modelos de cinco clases despues de las ramas binarias 325 if(num_saltos5==0) 326 { 327 for(uint i=0;i<(posiciones.size()/2);i++) 328 { 329 //Seleccion una imagen por clase 330 if(id_CSV%2==0) 331 { 332 for(int j=(2*num_images*i);j<=posiciones[2*i];j++) 333 { 334 images[j].copyTo(transicion); 335 im_arbol.push_back(transicion); 336 transicion.release(); 337 } 338 } 339 //Seleccion dos imagenes por clase 340 else 341 { 342 for(int j=(2*num_images*i);j<=posiciones[2*i];j++) 343 { 344 images[2*j].copyTo(transicion); 345 im_arbol.push_back(transicion); 346 transicion.release(); 347 images[2*j+1].copyTo(transicion); 348 im_arbol.push_back(transicion); 83 83 Estudio comparativo de modelos de identificación facial basados en correlación 349 transicion.release(); 350 } 351 } 352 //Creacion del modelo de cinco clases identificadoras 353 model.release(); 354 model = createFisherFaceRecognizer(); 355 arbol.push_back(model); 356 arbol[num_modelos]->train(im_arbol,labels); 357 num_modelos++; 358 im_arbol.clear(); 359 //Seleccion una imagen por clase 360 if(id_CSV%2==0) 361 { 362 for(int j=posiciones[2*i]+1;j<=posiciones[2*i+1];j++) 363 { 364 images[j].copyTo(transicion); 365 im_arbol.push_back(transicion); 366 transicion.release(); 367 } 368 } 369 //Seleccion dos imagenes por clase 370 else 371 { 372 for(int j=posiciones[2*i]+1;j<=posiciones[2*i+1];j++) 373 { 374 images[2*j].copyTo(transicion); 375 im_arbol.push_back(transicion); 376 transicion.release(); 377 images[2*j+1].copyTo(transicion); 378 im_arbol.push_back(transicion); 379 transicion.release(); 380 } 381 } 382 //Creacion del modelo de cinco clases identificadoras 383 model.release(); 384 model = createFisherFaceRecognizer(); 385 arbol.push_back(model); 386 arbol[num_modelos]->train(im_arbol,labels); 387 num_modelos++; 388 im_arbol.clear(); 389 } 390 //Tramos para los siguientes modelos 391 tam_posiciones=posiciones.size(); 392 for(int i=0;i<(tam_posiciones-1);i++) 393 { 394 if(i==0) 395 { 396 posiciones.push_back(((posiciones[0]+1)/5)-1); 397 posiciones.push_back((2*(posiciones[0]+1)/5)-1); 398 posiciones.push_back((3*(posiciones[0]+1)/5)-1); 399 posiciones.push_back((4*(posiciones[0]+1)/5)-1); 400 } 401 posiciones.push_back(((posiciones[0]+1)/5)+posiciones[i]); 402 posiciones.push_back((2*(posiciones[0]+1)/5)+posiciones[i]); 403 posiciones.push_back((3*(posiciones[0]+1)/5)+posiciones[i]); 404 posiciones.push_back((4*(posiciones[0]+1)/5)+posiciones[i]); 405 } 406 std::sort(posiciones.begin(),posiciones.end()); 407 num_saltos5++; 408 num_images/=5; 409 } 410 //Creacion de los modelos de cinco clases despues de una rama de un modelo con cinco clases 411 else 412 { 413 for(uint i=0;i<(posiciones.size()/5);i++) 414 { 415 //Seleccion una imagen por clase 416 if(id_CSV%2==0) 417 { 418 for(int j=(5*num_images*i);j<=posiciones[5*i];j++) 419 { 420 images[j].copyTo(transicion); 421 im_arbol.push_back(transicion); 422 transicion.release(); 423 } 424 } 425 //Seleccion dos imagenes por clase 426 else Anexo A. Documentación del código (Doxygen) 84 84 427 { 428 for(int j=(5*num_images*i);j<=posiciones[5*i];j++) 429 { 430 images[2*j].copyTo(transicion); 431 im_arbol.push_back(transicion); 432 transicion.release(); 433 images[2*j+1].copyTo(transicion); 434 im_arbol.push_back(transicion); 435 transicion.release(); 436 } 437 } 438 //Creacion del modelo de cinco clases identificadoras 439 model.release(); 440 model = createFisherFaceRecognizer(); 441 arbol.push_back(model); 442 arbol[num_modelos]->train(im_arbol,labels); 443 num_modelos++; 444 im_arbol.clear(); 445 //Seleccion una imagen por clase 446 if(id_CSV%2==0) 447 { 448 for(int j=posiciones[5*i]+1;j<=posiciones[5*i+1];j++) 449 { 450 images[j].copyTo(transicion); 451 im_arbol.push_back(transicion); 452 transicion.release(); 453 } 454 } 455 //Seleccion dos imagenes por clase 456 else 457 { 458 for(int j=posiciones[5*i]+1;j<=posiciones[5*i+1];j++) 459 { 460 images[2*j].copyTo(transicion); 461 im_arbol.push_back(transicion); 462 transicion.release(); 463 images[2*j+1].copyTo(transicion); 464 im_arbol.push_back(transicion); 465 transicion.release(); 466 } 467 } 468 //Creacion del modelo de cinco clases identificadoras 469 model.release(); 470 model = createFisherFaceRecognizer(); 471 arbol.push_back(model); 472 arbol[num_modelos]->train(im_arbol,labels); 473 num_modelos++; 474 im_arbol.clear(); 475 //Seleccion una imagen por clase 476 if(id_CSV%2==0) 477 { 478 for(int j=posiciones[5*i+1]+1;j<=posiciones[5*i+2];j++) 479 { 480 images[j].copyTo(transicion); 481 im_arbol.push_back(transicion); 482 transicion.release(); 483 } 484 } 485 //Seleccion dos imagenes por clase 486 else 487 { 488 for(int j=posiciones[5*i+1]+1;j<=posiciones[5*i+2];j++) 489 { 490 images[2*j].copyTo(transicion); 491 im_arbol.push_back(transicion); 492 transicion.release(); 493 images[2*j+1].copyTo(transicion); 494 im_arbol.push_back(transicion); 495 transicion.release(); 496 } 497 } 498 //Creacion del modelo de cinco clases identificadoras 499 model.release(); 500 model = createFisherFaceRecognizer(); 501 arbol.push_back(model); 502 arbol[num_modelos]->train(im_arbol,labels); 503 num_modelos++; 85 85 Estudio comparativo de modelos de identificación facial basados en correlación 504 im_arbol.clear(); 505 //Seleccion una imagen por clase 506 if(id_CSV%2==0) 507 { 508 for(int j=posiciones[5*i+2]+1;j<=posiciones[5*i+3];j++) 509 { 510 images[j].copyTo(transicion); 511 im_arbol.push_back(transicion); 512 transicion.release(); 513 } 514 } 515 //Seleccion dos imagenes por clase 516 else 517 { 518 for(int j=posiciones[5*i+2]+1;j<=posiciones[5*i+3];j++) 519 { 520 images[2*j].copyTo(transicion); 521 im_arbol.push_back(transicion); 522 transicion.release(); 523 images[2*j+1].copyTo(transicion); 524 im_arbol.push_back(transicion); 525 transicion.release(); 526 } 527 } 528 //Creacion del modelo de cinco clases identificadoras 529 model.release(); 530 model = createFisherFaceRecognizer(); 531 arbol.push_back(model); 532 arbol[num_modelos]->train(im_arbol,labels); 533 num_modelos++; 534 im_arbol.clear(); 535 //Seleccion una imagen por clase 536 if(id_CSV%2==0) 537 { 538 for(int j=posiciones[5*i+3]+1;j<=posiciones[5*i+4];j++) 539 { 540 images[j].copyTo(transicion); 541 im_arbol.push_back(transicion); 542 transicion.release(); 543 } 544 } 545 //Seleccion dos imagenes por clase 546 else 547 { 548 for(int j=posiciones[5*i+3]+1;j<=posiciones[5*i+4];j++) 549 { 550 images[2*j].copyTo(transicion); 551 im_arbol.push_back(transicion); 552 transicion.release(); 553 images[2*j+1].copyTo(transicion); 554 im_arbol.push_back(transicion); 555 transicion.release(); 556 } 557 } 558 //Creacion del modelo de cinco clases identificadoras 559 model.release(); 560 model = createFisherFaceRecognizer(); 561 arbol.push_back(model); 562 arbol[num_modelos]->train(im_arbol,labels); 563 num_modelos++; 564 im_arbol.clear(); 565 } 566 //Tramos para los siguientes modelos 567 tam_posiciones=posiciones.size(); 568 for(int i=0;i<(tam_posiciones-1);i++) 569 { 570 if(i==0) 571 { 572 posiciones.push_back(((posiciones[0]+1)/5)-1); 573 posiciones.push_back((2*(posiciones[0]+1)/5)-1); 574 posiciones.push_back((3*(posiciones[0]+1)/5)-1); 575 posiciones.push_back((4*(posiciones[0]+1)/5)-1); 576 } 577 posiciones.push_back(((posiciones[0]+1)/5)+posiciones[i]); 578 posiciones.push_back((2*(posiciones[0]+1)/5)+posiciones[i]); 579 posiciones.push_back((3*(posiciones[0]+1)/5)+posiciones[i]); 580 posiciones.push_back((4*(posiciones[0]+1)/5)+posiciones[i]); 581 } 582 std::sort(posiciones.begin(),posiciones.end()); Anexo A. Documentación del código (Doxygen) 86 86 583 num_saltos5++; 584 num_images/=5; 585 } 586 } 587 588 //Modelo arbol creado completo. Se procede a guardarlo 589 for(uint i=0;i<arbol.size();i++) 590 { 591 char intermedio[100]={0}; 592 sprintf(intermedio,fn_model.toUtf8().constData(),id_CSV,i); 593 arbol[i]->save(intermedio); 594 } 595 arbol.clear(); 596 char buf[40]={0}; 597 sprintf( buf, "%d\n%d\n%d\n", num_modelos, num_saltos2, num_saltos5); 598 ficheroArbol.open(QString("etc/Resultados/50x50/ParamArbolFisherFace%1.txt").arg(id_CSV).toUt f8().constData()); 599 ficheroArbol<<buf; 600 ficheroArbol.close(); 601 posiciones.clear(); 602 603 //Emision de la señal de fin de creacion del modelo 604 emit SignalFinCreacionModelo(); 605 } void QProceso::SlotCreaArbolLBPHFace (QString fn_model, int id_CSV)[slot] Funcion SlotCreaArbolLBPHFace. Crea el modelo LBPHFace con estructura en arbol. Crea el modelo LBPHFace con estructura en arbol. Primero crea los modelos binarios. A continuacion, crea los modelos con cinco clases identificadoras. Una vez creadas todas las ramas del arbol, procede a guardar el arbol completo. Por ultimo, indica la finalizacion de la creacion del arbol. Parámetros: fn_model Nombre con el cual se guardaran las ramas de arbol. id_CSV Identificador del fichero CSV. 1075 { 1076 num_saltos2=0; 1077 num_saltos5=0; 1078 num_modelos=0; 1079 1080 //Decision de una imagen por clase o dos imagenes por clase 1081 if(id_CSV%2!=0) 1082 { 1083 im_size=images.size()/2; 1084 num_images=images.size()/2; 1085 } 1086 else 1087 { 1088 im_size=images.size(); 1089 num_images=images.size(); 1090 } 1091 1092 //Creacion de las ramas de modelo binario 1093 while(num_images%2==0&&(int)posiciones.size()!=im_size) 1094 { 1095 //Relacion una imagen por clase 1096 if(id_CSV%2==0) 1097 { 1098 labels.clear(); 1099 for(int i=0;i<(num_images)/2;i++) 1100 labels.push_back(0); 1101 for(int i=0;i<(num_images)/2;i++) 1102 labels.push_back(1); 1103 } 1104 //Relacion dos imagenes por clase 1105 else 1106 { 1107 labels.clear(); 1108 for(int i=0;i<(num_images)/2;i++) 1109 { 1110 labels.push_back(0); 1111 labels.push_back(0); 87 87 Estudio comparativo de modelos de identificación facial basados en correlación 1112 } 1113 for(int i=0;i<(num_images)/2;i++) 1114 { 1115 labels.push_back(1); 1116 labels.push_back(1); 1117 } 1118 } 1119 //Creacion del modelo mujer - hombre 1120 if(num_saltos2==0) 1121 { 1122 model = createLBPHFaceRecognizer(); 1123 arbol.push_back(model); 1124 arbol[num_modelos]->train(images,labels); 1125 num_modelos++; 1126 num_saltos2++; 1127 posiciones.push_back(im_size/2-1); 1128 posiciones.push_back(im_size-1); 1129 num_images/=2; 1130 } 1131 //Creacion del resto de ramas binarias 1132 else 1133 { 1134 for(uint i=0;i<(posiciones.size()/2);i++) 1135 { 1136 //Seleccion una imagen por clase 1137 if(id_CSV%2==0) 1138 { 1139 for(int j=(2*num_images*i);j<=posiciones[2*i];j++) 1140 { 1141 images[j].copyTo(transicion); 1142 im_arbol.push_back(transicion); 1143 transicion.release(); 1144 } 1145 } 1146 //Seleccion dos imagen por clase 1147 else 1148 { 1149 for(int j=(2*num_images*i);j<=posiciones[2*i];j++) 1150 { 1151 images[2*j].copyTo(transicion); 1152 im_arbol.push_back(transicion); 1153 transicion.release(); 1154 images[2*j+1].copyTo(transicion); 1155 im_arbol.push_back(transicion); 1156 transicion.release(); 1157 } 1158 } 1159 //Creacion modelo binario 1160 model.release(); 1161 model = createLBPHFaceRecognizer(); 1162 arbol.push_back(model); 1163 arbol[num_modelos]->train(im_arbol,labels); 1164 num_modelos++; 1165 im_arbol.clear(); 1166 //Seleccion una imagen por clase 1167 if(id_CSV%2==0) 1168 { 1169 for(int j=posiciones[2*i]+1;j<=posiciones[2*i+1];j++) 1170 { 1171 images[j].copyTo(transicion); 1172 im_arbol.push_back(transicion); 1173 transicion.release(); 1174 } 1175 } 1176 //Seleccion dos imagenes por clase 1177 else 1178 { 1179 for(int j=posiciones[2*i]+1;j<=posiciones[2*i+1];j++) 1180 { 1181 images[2*j].copyTo(transicion); 1182 im_arbol.push_back(transicion); 1183 transicion.release(); 1184 images[2*j+1].copyTo(transicion); 1185 im_arbol.push_back(transicion); 1186 transicion.release(); 1187 } 1188 } 1189 //Creacion modelo binario 1190 model.release(); Anexo A. Documentación del código (Doxygen) 94 94 1630 predictedLabelArbol=0; 1631 prox_model=0; 1632 num_modelosBinarios=0; 1633 fin=false; 1634 1635 //Identificacion del sujeto por las ramas binarias 1636 for(int i=0;(i<num_saltos2)&&(!fin);i++) 1637 { 1638 confidence=0.0; 1639 predictedLabel=-1; 1640 arbol[prox_model]->predict(*test_im,predictedLabel,confidence); 1641 //Si no identifica al sujeto, se termina la ejecucion del arbol 1642 if(predictedLabel==-1) 1643 { 1644 fin=true; 1645 if(i==0) 1646 predictedLabelArbol=-1; 1647 else if(predictedLabelArbol<im_size/2) 1648 predictedLabelArbol=-2; 1649 else 1650 predictedLabelArbol=-3; 1651 } 1652 //Si el sujeto se identifica, pasa a la siguiente rama del arbol binario 1653 else 1654 { 1655 predictedLabelArbol+=predictedLabel*num_images/2; 1656 num_images/=2; 1657 prox_model=2*prox_model+predictedLabel+1; 1658 num_modelosBinarios+=(i+1)*2; 1659 } 1660 } 1661 1662 //Identificacion del sujeto por las ramas de los modelos de cinco clases identificadoras 1663 for(int i=0;(i<num_saltos5)&&(!fin);i++) 1664 { 1665 confidence=0.0; 1666 predictedLabel=-1; 1667 arbol[prox_model]->predict(*test_im,predictedLabel,confidence); 1668 //Si no identifica al sujeto, se termina la ejecucion del arbol 1669 if(predictedLabel==-1) 1670 { 1671 fin=true; 1672 if(predictedLabelArbol<im_size/2) 1673 predictedLabelArbol=-2; 1674 else 1675 predictedLabelArbol=-3; 1676 } 1677 //Si el sujeto se identifica, pasa a la siguiente rama de los modelos con cinco clases identificadoras 1678 else 1679 { 1680 predictedLabelArbol+=predictedLabel*num_images/5; 1681 num_images/=5; 1682 prox_model=num_modelosBinarios+(prox_model- (num_modelosBinarios/2))*5+predictedLabel+1; 1683 } 1684 } 1685 1686 //Emision de la señal de fin de identificacion del sujeto 1687 emit SignalFinIdentificacion(confidence,predictedLabelArbol); 1688 } Documentación de los datos miembro vector<Ptr<FaceRecognizer> > QProceso::arbol[private] Utilizado para la crecacion y carga de los distintos modelos con estructura en arbol double QProceso::confidence[private] Confianza de la identificacion realizada 95 95 Estudio comparativo de modelos de identificación facial basados en correlación ofstream QProceso::ficheroArbol[private] Fichero de escritura utilizado en la estructura en arbol para guardar el modelo ifstream QProceso::ficheroArbolLec[private] Fichero de lectura utilizado en la estructura en arbol para cargar el modelo bool QProceso::fin[private] Indica el final en la identificacion del modelo con estructura en arbol vector<Mat> QProceso::im_arbol[private] Imagenes usadas para la creacion de los modelos con estructura en arbol int QProceso::im_size[private] Numero de imagenes que forman el vector images vector<Mat> QProceso::images[private] Imagenes usadas para la creacion de los modelos vector<int> QProceso::labels[private] Contiene la correspondencia imagen - clase a identificar para la creacion de los modelos Ptr<FaceRecognizer> QProceso::model[private] Utilizado para la creacion y carga de los distintos modelos de identificacion int QProceso::num_images[private] Numero de imagenes que forman el vector images. Se modifica en la estructura en arbol int QProceso::num_modelos[private] Numero de modelos generados para la estructura en arbol int QProceso::num_modelosBinarios[private] Numero total de modelos binarios en la estructura en arbol int QProceso::num_saltos2[private] Numero de saltos de modelos binarios en la estructura en arbol int QProceso::num_saltos5[private] Numero de saltos de modelos con cinco clases en la estructura en arbol vector<int> QProceso::posiciones[private] Utilizado para la definicion de las ramas de los modelos con estructura en arbol int QProceso::predictedLabel[private] Prediccion realizada por un modelo de identificacion int QProceso::predictedLabelArbol[private] Prediccion realizada por un modelo con estructura en arbol int QProceso::prox_model[private] Utilizado para conocer el siguiente modelo a identificar en la estructura en arbol int QProceso::tam_posiciones[private] Tamaño del vector posiciones Anexo A. Documentación del código (Doxygen) 96 96 Mat QProceso::transicion[private] Utilizada para la seleccion de imagenes de cada rama del modelo con estructura en arbol La documentación para esta clase fue generada a partir de los siguientes ficheros:  src/Proceso.h  src/Proceso.cpp 97 97 Estudio comparativo de modelos de identificación facial basados en correlación Documentación de archivos Referencia del Archivo src/Cabeceras.h Contiene la inclusion de las clases y los ficheros *.h necesarios. Se debe incluir en todos los ficheros del proyecto. #include "Tipos.h" #include "FormPrincipal.h" #include "Proceso.h" #include "Config.h" #include <QtGui> #include "opencv2/opencv.hpp" #include "opencv2/core/core.hpp" #include "opencv2/highgui/highgui.hpp" #include <sys/time.h> #include <unistd.h> #include <iostream> #include <vector> Dependencia gráfica adjunta para Cabeceras.h: Gráfico de los archivos que directa o indirectamente incluyen a este archivo: Descripción detallada Contiene la inclusion de las clases y los ficheros *.h necesarios. Se debe incluir en todos los ficheros del proyecto. Autor: Maria Sierra Zapata Versión: 3.0 Fecha: 29 Junio 2015 Anexo A. Documentación del código (Doxygen) 98 98 Referencia del Archivo src/Config.cpp Contiene la definicion de la clase QConfig. #include "Config.h" Dependencia gráfica adjunta para Config.cpp: Descripción detallada Contiene la definicion de la clase QConfig. Autor: Maria Sierra Zapata Versión: 3.0 Fecha: 29 Junio 2015 99 99 Estudio comparativo de modelos de identificación facial basados en correlación Referencia del Archivo src/Config.h Contiene la cabecera de la clase QConfig. #include "Cabeceras.h" Dependencia gráfica adjunta para Config.h: Gráfico de los archivos que directa o indirectamente incluyen a este archivo: Clases  class QConfig Se encarga de la lectura del fichero de configuracion para la interfaz de la aplicacion y la escritura de los ficheros con los datos generados por los distintos modelos de identificacion. Variables  QConfig config Descripción detallada Contiene la cabecera de la clase QConfig. Autor: Maria Sierra Zapata Versión: 3.0 Fecha: 29 Junio 2015 Anexo A. Documentación del código (Doxygen) 100 100 Documentación de las variables QConfig config Instancia de la clase QConfig 101 101 Estudio comparativo de modelos de identificación facial basados en correlación Referencia del Archivo src/FormPrincipal.cpp Contiene la definicion de la clase QFormPrincipal. #include "FormPrincipal.h" Dependencia gráfica adjunta para FormPrincipal.cpp: Descripción detallada Contiene la definicion de la clase QFormPrincipal. Autor: Maria Sierra Zapata Versión: 3.0 Fecha: 29 Junio 2015 Anexo A. Documentación del código (Doxygen) 102 102 Referencia del Archivo src/FormPrincipal.h Contiene la cabecera de la clase QFormPrincipal. #include "Cabeceras.h" Dependencia gráfica adjunta para FormPrincipal.h: Gráfico de los archivos que directa o indirectamente incluyen a este archivo: Clases class QFormPrincipal Hereda de QWidget. Se encarga de gestionar la interfaz del programa. Variables QConfig config Descripción detallada Contiene la cabecera de la clase QFormPrincipal. Autor: Maria Sierra Zapata Versión: 3.0 Fecha: 29 Junio 2015 103 103 Estudio comparativo de modelos de identificación facial basados en correlación Documentación de las variables QConfig config Instancia de la clase QConfig Anexo A. Documentación del código (Doxygen) 110 110 111 ANEXO B. GENERADOR DE FICHEROS MAKEFILE AUTOMÁTICO Anexo B. Generador de Ficheros Makefile Automático 112 112 113 113 Estudio comparativo de modelos de identificación facial basados en correlación TEMPLATE = app VERSION = 3.0 QT += core \ gui CONFIG += qt \ debug_and_release \ build_all HEADERS += src/Tipos.h \ src/Config.h \ src/Proceso.h \ src/Cabeceras.h \ src/FormPrincipal.h SOURCES += src/Config.cpp \ src/Proceso.cpp \ src/FormPrincipal.cpp \ src/main.cpp LIBS += -L/usr/lib/ \ -L/usr/local/lib/ \ -lopencv_core \ -lopencv_highgui \ -lopencv_imgproc \ -lopencv_video \ -lopencv_objdetect \ -lopencv_contrib \ -lopencv_legacy unix:DEFINES = _TTY_POSIX_ win32:DEFINES = _TTY_WIN_ \ QWT_DLL \ QT_DLL CONFIG(debug, debug|release) { OBJECTS_DIR = .build/debug/obj MOC_DIR = .build/debug/moc DESTDIR = .build/debug/ TARGET = EstudioTFGd } else { OBJECTS_DIR = .build/release/obj MOC_DIR = .build/release/moc DESTDIR = .build/release/ TARGET = EstudioTFG target.path = EstudioTFG/ config.path = EstudioTFG/etc config.files = etc/* resources.path = EstudioTFG/resources resources.files = resources/* INSTALLS += target config resources } Anexo B. Generador de Ficheros Makefile Automático 114 114 115 ANEXO C. FICHEROS MATLAB PARA LA GENERACION DE LAS GRAFICAS Anexo C. Ficheros Matlab para la Generación de las Gráficas 116 116 117 117 Estudio comparativo de modelos de identificación facial basados en correlación Fichero analizaFicheroTiempos.m: % % Fichero: analizaFicheroTiempos.m % Autor: Maria Sierra Zapata % Fecha: 30/06/2015 % Version: 0.1 % % Breve Descripcion: % Apertura de los ficheros generados debido a la creacion y carga de % los diferentes modelos estudiados. Generacion de las graficas % correspondientes a los tiempos de los modelos. % % Datos que se obtienen: % Tiempo de creacion de todos los modelos % Tiempo de carga de todos los modelos % % Graficas generadas: % Tiempo de creacion - Numero de clases % Tiempo de carga - Numero de clases % cadena='%d=%f %f'; num_images=[10 50 100]; % Apertura y lectura del fichero nom_fichero='50x50/TiemposModelos_0.m'; tam50x50_0=leeFicheroTiempos(nom_fichero,cadena); nom_fichero='50x50/TiemposModelos_1.m'; tam50x50_1=leeFicheroTiempos(nom_fichero,cadena); nom_fichero='50x50/TiemposModelos_2.m'; tam50x50_2=leeFicheroTiempos(nom_fichero,cadena); nom_fichero='50x50/TiemposModelos_3.m'; tam50x50_3=leeFicheroTiempos(nom_fichero,cadena); nom_fichero='50x50/TiemposModelos_4.m'; tam50x50_4=leeFicheroTiempos(nom_fichero,cadena); nom_fichero='50x50/TiemposModelos_5.m'; tam50x50_5=leeFicheroTiempos(nom_fichero,cadena); nom_fichero='100x100/TiemposModelos_0.m'; tam100x100_0=leeFicheroTiempos(nom_fichero,cadena); nom_fichero='100x100/TiemposModelos_1.m'; tam100x100_1=leeFicheroTiempos(nom_fichero,cadena); nom_fichero='100x100/TiemposModelos_2.m'; tam100x100_2=leeFicheroTiempos(nom_fichero,cadena); nom_fichero='100x100/TiemposModelos_3.m'; tam100x100_3=leeFicheroTiempos(nom_fichero,cadena); nom_fichero='100x100/TiemposModelos_4.m'; tam100x100_4=leeFicheroTiempos(nom_fichero,cadena); nom_fichero='100x100/TiemposModelos_5.m'; tam100x100_5=leeFicheroTiempos(nom_fichero,cadena); nom_fichero='150x150/TiemposModelos_0.m'; tam150x150_0=leeFicheroTiempos(nom_fichero,cadena); nom_fichero='150x150/TiemposModelos_1.m'; tam150x150_1=leeFicheroTiempos(nom_fichero,cadena); nom_fichero='150x150/TiemposModelos_2.m'; tam150x150_2=leeFicheroTiempos(nom_fichero,cadena); nom_fichero='150x150/TiemposModelos_3.m'; tam150x150_3=leeFicheroTiempos(nom_fichero,cadena); nom_fichero='150x150/TiemposModelos_4.m'; tam150x150_4=leeFicheroTiempos(nom_fichero,cadena); nom_fichero='150x150/TiemposModelos_5.m'; tam150x150_5=leeFicheroTiempos(nom_fichero,cadena); nom_fichero='200x200/TiemposModelos_0.m'; tam200x200_0=leeFicheroTiempos(nom_fichero,cadena); nom_fichero='200x200/TiemposModelos_1.m'; tam200x200_1=leeFicheroTiempos(nom_fichero,cadena); nom_fichero='200x200/TiemposModelos_2.m'; tam200x200_2=leeFicheroTiempos(nom_fichero,cadena); nom_fichero='200x200/TiemposModelos_3.m'; tam200x200_3=leeFicheroTiempos(nom_fichero,cadena); nom_fichero='200x200/TiemposModelos_4.m'; tam200x200_4=leeFicheroTiempos(nom_fichero,cadena); nom_fichero='200x200/TiemposModelos_5.m'; tam200x200_5=leeFicheroTiempos(nom_fichero,cadena); Anexo C. Ficheros Matlab para la Generación de las Gráficas 118 118 % Creacion de la grafica para un modelo especifico. Modificando y, se % selecciona la grafica de tiempo de carga o de tiempo de creacion. % Modificando x se selecciona el modelo a representar. Representacion en % funcion del numero de clases. x=3; y=3; tiempoSimUna=[tam50x50_0(x,y) tam50x50_2(x,y) tam50x50_4(x,y)]; tiempoArbUna=[tam50x50_0(x+3,y) tam50x50_2(x+3,y) tam50x50_4(x+3,y)]; tiempoSimDos=[tam50x50_1(x,y) tam50x50_3(x,y) tam50x50_5(x,y)]; tiempoArbDos=[tam50x50_1(x+3,y) tam50x50_3(x+3,y) tam50x50_5(x+3,y)]; subplot(2,2,1) plot(num_images, tiempoSimUna,'.-', num_images, tiempoArbUna, '.-', num_images, tiempoSimDos, '.- ', num_images, tiempoArbDos, '.-') xlabel('Num Clases') ylabel('Segundos') legend('S - 1:1','A - 1:1', 'S - 2:1', 'A - 2:1', 'Location', 'Best') title('Tam Imagen 50x50') tiempoSimUna=[tam100x100_0(x,y) tam100x100_2(x,y) tam100x100_4(x,y)]; tiempoArbUna=[tam100x100_0(x+3,y) tam100x100_2(x+3,y) tam100x100_4(x+3,y)]; tiempoSimDos=[tam100x100_1(x,y) tam100x100_3(x,y) tam100x100_5(x,y)]; tiempoArbDos=[tam100x100_1(x+3,y) tam100x100_3(x+3,y) tam100x100_5(x+3,y)]; subplot(2,2,2) plot(num_images, tiempoSimUna,'.-', num_images, tiempoArbUna, '.-', num_images, tiempoSimDos, '.- ', num_images, tiempoArbDos, '.-') xlabel('Num Clases') ylabel('Segundos') legend('S - 1:1','A - 1:1', 'S - 2:1', 'A - 2:1', 'Location', 'Best') title('Tam Imagen 100x100') tiempoSimUna=[tam150x150_0(x,y) tam150x150_2(x,y) tam150x150_4(x,y)]; tiempoArbUna=[tam150x150_0(x+3,y) tam150x150_2(x+3,y) tam150x150_4(x+3,y)]; tiempoSimDos=[tam150x150_1(x,y) tam150x150_3(x,y) tam150x150_5(x,y)]; tiempoArbDos=[tam150x150_1(x+3,y) tam150x150_3(x+3,y) tam150x150_5(x+3,y)]; subplot(2,2,3) plot(num_images, tiempoSimUna,'.-', num_images, tiempoArbUna, '.-', num_images, tiempoSimDos, '.- ', num_images, tiempoArbDos, '.-') xlabel('Num Clases') ylabel('Segundos') legend('S - 1:1','A - 1:1', 'S - 2:1', 'A - 2:1', 'Location', 'Best') title('Tam Imagen 150x150') tiempoSimUna=[tam200x200_0(x,y) tam200x200_2(x,y) tam100x100_4(x,y)]; tiempoArbUna=[tam200x200_0(x+3,y) tam200x200_2(x+3,y) tam100x100_4(x+3,y)]; tiempoSimDos=[tam200x200_1(x,y) tam200x200_3(x,y) tam100x100_5(x,y)]; tiempoArbDos=[tam200x200_1(x+3,y) tam200x200_3(x+3,y) tam100x100_5(x+3,y)]; subplot(2,2,4) plot(num_images, tiempoSimUna,'.-', num_images, tiempoArbUna, '.-', num_images, tiempoSimDos, '.- ', num_images, tiempoArbDos, '.-') xlabel('Num Clases') ylabel('Segundos') legend('S - 1:1','A - 1:1', 'S - 2:1', 'A - 2:1', 'Location', 'Best') title('Tam Imagen 200x200') Fichero de la función leeFicheroTiempos.m: % % Fichero: leeFicheroTiempos.m % Autor: Maria Sierra Zapata % Fecha: 30/06/2015 % Version: 0.1 % % Breve Descripcion: % Funcion que se encarga de leer los datos de un fichero con un % formato especifico. % % Parametros de Entrada: % nom_fichero : Contiene la cadena del fichero del que se quiere % leer los datos. 119 119 Estudio comparativo de modelos de identificación facial basados en correlación % cadena : Contiene el formato con el que se desea leer el fichero. % % Parametros de Salida: % Y : Matriz que contiene los datos obtenidos del fichero. % function Y = leeFicheroTiempos(nom_fichero, cadena) % Apertura del fichero fichero=fopen(nom_fichero,'r'); fgets(fichero); % Lectura del fichero X=fscanf(fichero,cadena); Y=reshape(X,3,size(X,1)/3)'; % Cierre del fichero fclose(fichero); end Fichero analizaFicheroPersona50x50.m: % % Fichero: analizaFicheroPersona50x50.m % Autor: Maria Sierra Zapata % Fecha: 01/07/2015 % Version: 0.1 % % Breve Descripcion: % Apertura de los ficheros generados debido a la % identificacion de personas para un modelo y con tamaño de imagen % 50x50 pixeles. Seleccion de los datos para la generacion de las % graficas para el estudio. % % Datos que se obtienen: % Tiempo Medio de Identificacion % Falsos Positivos Mujer % Falsos Positivos Hombre % Falsos Positivos % Tasa de Acierto Hombre % Tasa de Acierto Mujer % Tasa de Acierto % cadena='%d=%f %f %d'; num_images=[10 50 100]; % Apertura y lectura del fichero nom_fichero='50x50/ResultadosHombreM2_02.m'; dat=leeFicheroPersona(nom_fichero,cadena); % Obtencion de los datos del fichero [m,n]=size(dat); for i=1:m if i==1 if dat(i,2)==0 tmi50x50S1=0.0001; else tmi50x50S1=dat(i,2); end if dat(i,4)>5 fpm50x50S1=0; tah50x50S1=1; else fpm50x50S1=1; tah50x50S1=0; end if dat(i,4)==i+5 fp50x50S1=0; ta50x50S1=1; else fp50x50S1=1; ta50x50S1=0; end else if dat(i,2)==0 tmi50x50S1=[tmi50x50S1 0.0001]; else Anexo C. Ficheros Matlab para la Generación de las Gráficas 126 126 fp50x50S2=[fp50x50S2 0]; ta50x50S2=[ta50x50S2 1]; else fp50x50S2=[fp50x50S2 1]; ta50x50S2=[ta50x50S2 0]; end end end nom_fichero='50x50/ResultadosMujerM3_12.m'; dat=leeFicheroPersona(nom_fichero,cadena); [m,n]=size(dat); for i=1:m if dat(i,2)==0 tmi50x50S2=[tmi50x50S2 0.0001]; else tmi50x50S2=[tmi50x50S2 dat(i,2)]; end if dat(i,4)==i&&dat(i,4)<=5 fp50x50S2=[fp50x50S2 0]; ta50x50S2=[ta50x50S2 1]; else fp50x50S2=[fp50x50S2 1]; ta50x50S2=[ta50x50S2 0]; end if i==1 if dat(i,4)<=5 fph50x50S2=0; tam50x50S2=1; else fph50x50S2=1; tam50x50S2=0; end else if dat(i,4)<=5 fph50x50S2=[fph50x50S2 0]; tam50x50S2=[tam50x50S2 1]; else fph50x50S2=[fph50x50S2 1]; tam50x50S2=[tam50x50S2 0]; end end end nom_fichero='50x50/ResultadosHombreM3_15.m'; dat=leeFicheroPersona(nom_fichero,cadena); [m,n]=size(dat); for i=1:m if i==1 if dat(i,2)==0 tmi50x50A2=0.0001; else tmi50x50A2=dat(i,2); end if dat(i,4)>5 fpm50x50A2=0; tah50x50A2=1; else fpm50x50A2=1; tah50x50A2=0; end if dat(i,4)==i+5 fp50x50A2=0; ta50x50A2=1; else fp50x50A2=1; ta50x50A2=0; end else if dat(i,2)==0 tmi50x50A2=[tmi50x50A2 0.0001]; else tmi50x50A2=[tmi50x50A2 dat(i,2)]; end if dat(i,4)>5 fpm50x50A2=[fpm50x50A2 0]; tah50x50A2=[tah50x50A2 1]; else fpm50x50A2=[fpm50x50A2 1]; 127 127 Estudio comparativo de modelos de identificación facial basados en correlación tah50x50A2=[tah50x50A2 0]; end if dat(i,4)==i+5 fp50x50A2=[fp50x50A2 0]; ta50x50A2=[ta50x50A2 1]; else fp50x50A2=[fp50x50A2 1]; ta50x50A2=[ta50x50A2 0]; end end end nom_fichero='50x50/ResultadosMujerM3_15.m'; dat=leeFicheroPersona(nom_fichero,cadena); [m,n]=size(dat); for i=1:m if dat(i,2)==0 tmi50x50A2=[tmi50x50A2 0.0001]; else tmi50x50A2=[tmi50x50A2 dat(i,2)]; end if dat(i,4)==i&&dat(i,4)<=5 fp50x50A2=[fp50x50A2 0]; ta50x50A2=[ta50x50A2 1]; else fp50x50A2=[fp50x50A2 1]; ta50x50A2=[ta50x50A2 0]; end if i==1 if dat(i,4)<=5 fph50x50A2=0; tam50x50A2=1; else fph50x50A2=1; tam50x50A2=0; end else if dat(i,4)<=5 fph50x50A2=[fph50x50A2 0]; tam50x50A2=[tam50x50A2 1]; else fph50x50A2=[fph50x50A2 1]; tam50x50A2=[tam50x50A2 0]; end end end nom_fichero='50x50/ResultadosHombreM3_22.m'; dat=leeFicheroPersona(nom_fichero,cadena); [m,n]=size(dat); for i=1:m if dat(i,2)==0 tmi50x50S1=[tmi50x50S1 0.0001]; else tmi50x50S1=[tmi50x50S1 dat(i,2)]; end if dat(i,4)>25 fpm50x50S1=[fpm50x50S1 0]; tah50x50S1=[tah50x50S1 1]; else fpm50x50S1=[fpm50x50S1 1]; tah50x50S1=[tah50x50S1 0]; end if dat(i,4)==i+25 fp50x50S1=[fp50x50S1 0]; ta50x50S1=[ta50x50S1 1]; else fp50x50S1=[fp50x50S1 1]; ta50x50S1=[ta50x50S1 0]; end end nom_fichero='50x50/ResultadosMujerM3_22.m'; dat=leeFicheroPersona(nom_fichero,cadena); [m,n]=size(dat); for i=1:m if dat(i,2)==0 tmi50x50S1=[tmi50x50S1 0.0001]; else tmi50x50S1=[tmi50x50S1 dat(i,2)]; Anexo C. Ficheros Matlab para la Generación de las Gráficas 128 128 end if dat(i,4)==i&&dat(i,4)<=25 fp50x50S1=[fp50x50S1 0]; ta50x50S1=[ta50x50S1 1]; else fp50x50S1=[fp50x50S1 1]; ta50x50S1=[ta50x50S1 0]; end if dat(i,4)<=25 fph50x50S1=[fph50x50S1 0]; tam50x50S1=[tam50x50S1 1]; else fph50x50S1=[fph50x50S1 1]; tam50x50S1=[tam50x50S1 0]; end end nom_fichero='50x50/ResultadosHombreM3_25.m'; dat=leeFicheroPersona(nom_fichero,cadena); [m,n]=size(dat); for i=1:m if dat(i,2)==0 tmi50x50A1=[tmi50x50A1 0.0001]; else tmi50x50A1=[tmi50x50A1 dat(i,2)]; end if dat(i,4)>25 fpm50x50A1=[fpm50x50A1 0]; tah50x50A1=[tah50x50A1 1]; else fpm50x50A1=[fpm50x50A1 1]; tah50x50A1=[tah50x50A1 0]; end if dat(i,4)==i+25 fp50x50A1=[fp50x50A1 0]; ta50x50A1=[ta50x50A1 1]; else fp50x50A1=[fp50x50A1 1]; ta50x50A1=[ta50x50A1 0]; end end nom_fichero='50x50/ResultadosMujerM3_25.m'; dat=leeFicheroPersona(nom_fichero,cadena); [m,n]=size(dat); for i=1:m if dat(i,2)==0 tmi50x50A1=[tmi50x50A1 0.0001]; else tmi50x50A1=[tmi50x50A1 dat(i,2)]; end if dat(i,4)==i&&dat(i,4)<=25 fp50x50A1=[fp50x50A1 0]; ta50x50A1=[ta50x50A1 1]; else fp50x50A1=[fp50x50A1 1]; ta50x50A1=[ta50x50A1 0]; end if dat(i,4)<=25 fph50x50A1=[fph50x50A1 0]; tam50x50A1=[tam50x50A1 1]; else fph50x50A1=[fph50x50A1 1]; tam50x50A1=[tam50x50A1 0]; end end nom_fichero='50x50/ResultadosHombreM3_32.m'; dat=leeFicheroPersona(nom_fichero,cadena); [m,n]=size(dat); for i=1:m if dat(i,2)==0 tmi50x50S2=[tmi50x50S2 0.0001]; else tmi50x50S2=[tmi50x50S2 dat(i,2)]; end if dat(i,4)>25 fpm50x50S2=[fpm50x50S2 0]; 129 129 Estudio comparativo de modelos de identificación facial basados en correlación tah50x50S2=[tah50x50S2 1]; else fpm50x50S2=[fpm50x50S2 1]; tah50x50S2=[tah50x50S2 0]; end if dat(i,4)==i+25 fp50x50S2=[fp50x50S2 0]; ta50x50S2=[ta50x50S2 1]; else fp50x50S2=[fp50x50S2 1]; ta50x50S2=[ta50x50S2 0]; end end nom_fichero='50x50/ResultadosMujerM3_32.m'; dat=leeFicheroPersona(nom_fichero,cadena); [m,n]=size(dat); for i=1:m if dat(i,2)==0 tmi50x50S2=[tmi50x50S2 0.0001]; else tmi50x50S2=[tmi50x50S2 dat(i,2)]; end if dat(i,4)==i&&dat(i,4)<=25 fp50x50S2=[fp50x50S2 0]; ta50x50S2=[ta50x50S2 1]; else fp50x50S2=[fp50x50S2 1]; ta50x50S2=[ta50x50S2 0]; end if dat(i,4)<=25 fph50x50S2=[fph50x50S2 0]; tam50x50S2=[tam50x50S2 1]; else fph50x50S2=[fph50x50S2 1]; tam50x50S2=[tam50x50S2 0]; end end nom_fichero='50x50/ResultadosHombreM3_35.m'; dat=leeFicheroPersona(nom_fichero,cadena); [m,n]=size(dat); for i=1:m if dat(i,2)==0 tmi50x50A2=[tmi50x50A2 0.0001]; else tmi50x50A2=[tmi50x50A2 dat(i,2)]; end if dat(i,4)>25 fpm50x50A2=[fpm50x50A2 0]; tah50x50A2=[tah50x50A2 1]; else fpm50x50A2=[fpm50x50A2 1]; tah50x50A2=[tah50x50A2 0]; end if dat(i,4)==i+25 fp50x50A2=[fp50x50A2 0]; ta50x50A2=[ta50x50A2 1]; else fp50x50A2=[fp50x50A2 1]; ta50x50A2=[ta50x50A2 0]; end end nom_fichero='50x50/ResultadosMujerM3_35.m'; dat=leeFicheroPersona(nom_fichero,cadena); [m,n]=size(dat); for i=1:m if dat(i,2)==0 tmi50x50A2=[tmi50x50A2 0.0001]; else tmi50x50A2=[tmi50x50A2 dat(i,2)]; end if dat(i,4)==i&&dat(i,4)<=25 fp50x50A2=[fp50x50A2 0]; ta50x50A2=[ta50x50A2 1]; else fp50x50A2=[fp50x50A2 1]; ta50x50A2=[ta50x50A2 0]; end Anexo C. Ficheros Matlab para la Generación de las Gráficas 130 130 if dat(i,4)<=25 fph50x50A2=[fph50x50A2 0]; tam50x50A2=[tam50x50A2 1]; else fph50x50A2=[fph50x50A2 1]; tam50x50A2=[tam50x50A2 0]; end end nom_fichero='50x50/ResultadosHombreM3_42.m'; dat=leeFicheroPersona(nom_fichero,cadena); [m,n]=size(dat); for i=1:m if dat(i,2)==0 tmi50x50S1=[tmi50x50S1 0.0001]; else tmi50x50S1=[tmi50x50S1 dat(i,2)]; end if dat(i,4)>50 fpm50x50S1=[fpm50x50S1 0]; tah50x50S1=[tah50x50S1 1]; else fpm50x50S1=[fpm50x50S1 1]; tah50x50S1=[tah50x50S1 0]; end if dat(i,4)==i+50 fp50x50S1=[fp50x50S1 0]; ta50x50S1=[ta50x50S1 1]; else fp50x50S1=[fp50x50S1 1]; ta50x50S1=[ta50x50S1 0]; end end nom_fichero='50x50/ResultadosMujerM3_42.m'; dat=leeFicheroPersona(nom_fichero,cadena); [m,n]=size(dat); for i=1:m if dat(i,2)==0 tmi50x50S1=[tmi50x50S1 0.0001]; else tmi50x50S1=[tmi50x50S1 dat(i,2)]; end if dat(i,4)==i&&dat(i,4)<=50 fp50x50S1=[fp50x50S1 0]; ta50x50S1=[ta50x50S1 1]; else fp50x50S1=[fp50x50S1 1]; ta50x50S1=[ta50x50S1 0]; end if dat(i,4)<=50 fph50x50S1=[fph50x50S1 0]; tam50x50S1=[tam50x50S1 1]; else fph50x50S1=[fph50x50S1 1]; tam50x50S1=[tam50x50S1 0]; end end nom_fichero='50x50/ResultadosHombreM3_45.m'; dat=leeFicheroPersona(nom_fichero,cadena); [m,n]=size(dat); for i=1:m if dat(i,2)==0 tmi50x50A1=[tmi50x50A1 0.0001]; else tmi50x50A1=[tmi50x50A1 dat(i,2)]; end if dat(i,4)>50 fpm50x50A1=[fpm50x50A1 0]; tah50x50A1=[tah50x50A1 1]; else fpm50x50A1=[fpm50x50A1 1]; tah50x50A1=[tah50x50A1 0]; end if dat(i,4)==i+50 fp50x50A1=[fp50x50A1 0]; ta50x50A1=[ta50x50A1 1]; 131 131 Estudio comparativo de modelos de identificación facial basados en correlación else fp50x50A1=[fp50x50A1 1]; ta50x50A1=[ta50x50A1 0]; end end nom_fichero='50x50/ResultadosMujerM3_45.m'; dat=leeFicheroPersona(nom_fichero,cadena); [m,n]=size(dat); for i=1:m if dat(i,2)==0 tmi50x50A1=[tmi50x50A1 0.0001]; else tmi50x50A1=[tmi50x50A1 dat(i,2)]; end if dat(i,4)==i&&dat(i,4)<=50 fp50x50A1=[fp50x50A1 0]; ta50x50A1=[ta50x50A1 1]; else fp50x50A1=[fp50x50A1 1]; ta50x50A1=[ta50x50A1 0]; end if dat(i,4)<=50 fph50x50A1=[fph50x50A1 0]; tam50x50A1=[tam50x50A1 1]; else fph50x50A1=[fph50x50A1 1]; tam50x50A1=[tam50x50A1 0]; end end nom_fichero='50x50/ResultadosHombreM3_52.m'; dat=leeFicheroPersona(nom_fichero,cadena); [m,n]=size(dat); for i=1:m if dat(i,2)==0 tmi50x50S2=[tmi50x50S2 0.0001]; else tmi50x50S2=[tmi50x50S2 dat(i,2)]; end if dat(i,4)>50 fpm50x50S2=[fpm50x50S2 0]; tah50x50S2=[tah50x50S2 1]; else fpm50x50S2=[fpm50x50S2 1]; tah50x50S2=[tah50x50S2 0]; end if dat(i,4)==i+50 fp50x50S2=[fp50x50S2 0]; ta50x50S2=[ta50x50S2 1]; else fp50x50S2=[fp50x50S2 1]; ta50x50S2=[ta50x50S2 0]; end end nom_fichero='50x50/ResultadosMujerM3_52.m'; dat=leeFicheroPersona(nom_fichero,cadena); [m,n]=size(dat); for i=1:m if dat(i,2)==0 tmi50x50S2=[tmi50x50S2 0.0001]; else tmi50x50S2=[tmi50x50S2 dat(i,2)]; end if dat(i,4)==i&&dat(i,4)<=50 fp50x50S2=[fp50x50S2 0]; ta50x50S2=[ta50x50S2 1]; else fp50x50S2=[fp50x50S2 1]; ta50x50S2=[ta50x50S2 0]; end if dat(i,4)<=50 fph50x50S2=[fph50x50S2 0]; tam50x50S2=[tam50x50S2 1]; else fph50x50S2=[fph50x50S2 1]; tam50x50S2=[tam50x50S2 0]; end end Anexo C. Ficheros Matlab para la Generación de las Gráficas 132 132 nom_fichero='50x50/ResultadosHombreM3_55.m'; dat=leeFicheroPersona(nom_fichero,cadena); [m,n]=size(dat); for i=1:m if dat(i,2)==0 tmi50x50A2=[tmi50x50A2 0.0001]; else tmi50x50A2=[tmi50x50A2 dat(i,2)]; end if dat(i,4)>50 fpm50x50A2=[fpm50x50A2 0]; tah50x50A2=[tah50x50A2 1]; else fpm50x50A2=[fpm50x50A2 1]; tah50x50A2=[tah50x50A2 0]; end if dat(i,4)==i+50 fp50x50A2=[fp50x50A2 0]; ta50x50A2=[ta50x50A2 1]; else fp50x50A2=[fp50x50A2 1]; ta50x50A2=[ta50x50A2 0]; end end nom_fichero='50x50/ResultadosMujerM3_55.m'; dat=leeFicheroPersona(nom_fichero,cadena); [m,n]=size(dat); for i=1:m if dat(i,2)==0 tmi50x50A2=[tmi50x50A2 0.0001]; else tmi50x50A2=[tmi50x50A2 dat(i,2)]; end if dat(i,4)==i&&dat(i,4)<=50 fp50x50A2=[fp50x50A2 0]; ta50x50A2=[ta50x50A2 1]; else fp50x50A2=[fp50x50A2 1]; ta50x50A2=[ta50x50A2 0]; end if dat(i,4)<=50 fph50x50A2=[fph50x50A2 0]; tam50x50A2=[tam50x50A2 1]; else fph50x50A2=[fph50x50A2 1]; tam50x50A2=[tam50x50A2 0]; end end % Generados todos los datos, se hace la clasificacion para 10 clases, % 50 clases y 100 clases. m=size(tmi50x50S1,2); tmi50x50S12=reshape(tmi50x50S1,m/6,6); tmi50x50S1=[(sum(tmi50x50S12(:,1))+sum(tmi50x50S12(:,4)))/(m/3) (sum(tmi50x50S12(:,2))+sum(tmi50x50S12(:,5)))/(m/3) (sum(tmi50x50S12(:,3))+sum(tmi50x50S12(:,6)))/(m/3)]; tmi50x50S12=0; m=size(tmi50x50A1,2); tmi50x50A12=reshape(tmi50x50A1,m/6,6); tmi50x50A1=[(sum(tmi50x50A12(:,1))+sum(tmi50x50A12(:,4)))/(m/3) (sum(tmi50x50A12(:,2))+sum(tmi50x50A12(:,5)))/(m/3) (sum(tmi50x50A12(:,3))+sum(tmi50x50A12(:,6)))/(m/3)]; tmi50x50A12=0; m=size(tmi50x50S2,2); tmi50x50S22=reshape(tmi50x50S2,m/3,3); tmi50x50S2=[sum(tmi50x50S22(:,1))/(m/3) sum(tmi50x50S22(:,2))/(m/3) sum(tmi50x50S22(:,3))/(m/3)]; tmi50x50S22=0; m=size(tmi50x50A2,2); tmi50x50A22=reshape(tmi50x50A2,m/3,3); tmi50x50A2=[sum(tmi50x50A22(:,1))/(m/3) sum(tmi50x50A22(:,2))/(m/3) sum(tmi50x50A22(:,3))/(m/3)]; tmi50x50A22=0; 133 133 Estudio comparativo de modelos de identificación facial basados en correlación m=size(fpm50x50S1,2); fpm50x50S12=reshape(fpm50x50S1,m/6,6); fpm50x50S1=[(sum(fpm50x50S12(:,1))+sum(fpm50x50S12(:,4)))/(m/3) (sum(fpm50x50S12(:,2))+sum(fpm50x50S12(:,5)))/(m/3) (sum(fpm50x50S12(:,3))+sum(fpm50x50S12(:,6)))/(m/3)]; fpm50x50S12=0; m=size(fpm50x50A1,2); fpm50x50A12=reshape(fpm50x50A1,m/6,6); fpm50x50A1=[(sum(fpm50x50A12(:,1))+sum(fpm50x50A12(:,4)))/(m/3) (sum(fpm50x50A12(:,2))+sum(fpm50x50A12(:,5)))/(m/3) (sum(fpm50x50A12(:,3))+sum(fpm50x50A12(:,6)))/(m/3)]; fpm50x50A12=0; m=size(fpm50x50S2,2); fpm50x50S22=reshape(fpm50x50S2,m/3,3); fpm50x50S2=[sum(fpm50x50S22(:,1))/(m/3) sum(fpm50x50S22(:,2))/(m/3) sum(fpm50x50S22(:,3))/(m/3)]; fpm50x50S22=0; m=size(fpm50x50A2,2); fpm50x50A22=reshape(fpm50x50A2,m/3,3); fpm50x50A2=[sum(fpm50x50A22(:,1))/(m/3) sum(fpm50x50A22(:,2))/(m/3) sum(fpm50x50A22(:,3))/(m/3)]; fpm50x50A22=0; m=size(fph50x50S1,2); fph50x50S12=reshape(fph50x50S1,m/6,6); fph50x50S1=[(sum(fph50x50S12(:,1))+sum(fph50x50S12(:,4)))/(m/3) (sum(fph50x50S12(:,2))+sum(fph50x50S12(:,5)))/(m/3) (sum(fph50x50S12(:,3))+sum(fph50x50S12(:,6)))/(m/3)]; fph50x50S12=0; m=size(fph50x50A1,2); fph50x50A12=reshape(fph50x50A1,m/6,6); fph50x50A1=[(sum(fph50x50A12(:,1))+sum(fph50x50A12(:,4)))/(m/3) (sum(fph50x50A12(:,2))+sum(fph50x50A12(:,5)))/(m/3) (sum(fph50x50A12(:,3))+sum(fph50x50A12(:,6)))/(m/3)]; fph50x50A12=0; m=size(fph50x50S2,2); fph50x50S22=reshape(fph50x50S2,m/3,3); fph50x50S2=[sum(fph50x50S22(:,1))/(m/3) sum(fph50x50S22(:,2))/(m/3) sum(fph50x50S22(:,3))/(m/3)]; fph50x50S22=0; m=size(fph50x50A2,2); fph50x50A22=reshape(fph50x50A2,m/3,3); fph50x50A2=[sum(fph50x50A22(:,1))/(m/3) sum(fph50x50A22(:,2))/(m/3) sum(fph50x50A22(:,3))/(m/3)]; fph50x50A22=0; m=size(tah50x50S1,2); tah50x50S12=reshape(tah50x50S1,m/6,6); tah50x50S1=[(sum(tah50x50S12(:,1))+sum(tah50x50S12(:,4)))/(m/3) (sum(tah50x50S12(:,2))+sum(tah50x50S12(:,5)))/(m/3) (sum(tah50x50S12(:,3))+sum(tah50x50S12(:,6)))/(m/3)]; tah50x50S12=0; m=size(tah50x50A1,2); tah50x50A12=reshape(tah50x50A1,m/6,6); tah50x50A1=[(sum(tah50x50A12(:,1))+sum(tah50x50A12(:,4)))/(m/3) (sum(tah50x50A12(:,2))+sum(tah50x50A12(:,5)))/(m/3) (sum(tah50x50A12(:,3))+sum(tah50x50A12(:,6)))/(m/3)]; tah50x50A12=0; m=size(tah50x50S2,2); tah50x50S22=reshape(tah50x50S2,m/3,3); tah50x50S2=[sum(tah50x50S22(:,1))/(m/3) sum(tah50x50S22(:,2))/(m/3) sum(tah50x50S22(:,3))/(m/3)]; tah50x50S22=0; m=size(tah50x50A2,2); tah50x50A22=reshape(tah50x50A2,m/3,3); tah50x50A2=[sum(tah50x50A22(:,1))/(m/3) sum(tah50x50A22(:,2))/(m/3) sum(tah50x50A22(:,3))/(m/3)]; tah50x50A22=0; m=size(tam50x50S1,2); tam50x50S12=reshape(tam50x50S1,m/6,6); Anexo C. Ficheros Matlab para la Generación de las Gráficas 134 134 tam50x50S1=[(sum(tam50x50S12(:,1))+sum(tam50x50S12(:,4)))/(m/3) (sum(tam50x50S12(:,2))+sum(tam50x50S12(:,5)))/(m/3) (sum(tam50x50S12(:,3))+sum(tam50x50S12(:,6)))/(m/3)]; tam50x50S12=0; m=size(tam50x50A1,2); tam50x50A12=reshape(tam50x50A1,m/6,6); tam50x50A1=[(sum(tam50x50A12(:,1))+sum(tam50x50A12(:,4)))/(m/3) (sum(tam50x50A12(:,2))+sum(tam50x50A12(:,5)))/(m/3) (sum(tam50x50A12(:,3))+sum(tam50x50A12(:,6)))/(m/3)]; tam50x50A12=0; m=size(tam50x50S2,2); tam50x50S22=reshape(tam50x50S2,m/3,3); tam50x50S2=[sum(tam50x50S22(:,1))/(m/3) sum(tam50x50S22(:,2))/(m/3) sum(tam50x50S22(:,3))/(m/3)]; tam50x50S22=0; m=size(tam50x50A2,2); tam50x50A22=reshape(tam50x50A2,m/3,3); tam50x50A2=[sum(tam50x50A22(:,1))/(m/3) sum(tam50x50A22(:,2))/(m/3) sum(tam50x50A22(:,3))/(m/3)]; tam50x50A22=0; m=size(fp50x50S1,2); fp50x50S12=reshape(fp50x50S1,m/6,6); fp50x50S1=[(sum(fp50x50S12(:,1))+sum(fp50x50S12(:,4)))/(m/3) (sum(fp50x50S12(:,2))+sum(fp50x50S12(:,5)))/(m/3) (sum(fp50x50S12(:,3))+sum(fp50x50S12(:,6)))/(m/3)]; fp50x50S12=0; m=size(fp50x50A1,2); fp50x50A12=reshape(fp50x50A1,m/6,6); fp50x50A1=[(sum(fp50x50A12(:,1))+sum(fp50x50A12(:,4)))/(m/3) (sum(fp50x50A12(:,2))+sum(fp50x50A12(:,5)))/(m/3) (sum(fp50x50A12(:,3))+sum(fp50x50A12(:,6)))/(m/3)]; fp50x50A12=0; m=size(fp50x50S2,2); fp50x50S22=reshape(fp50x50S2,m/3,3); fp50x50S2=[sum(fp50x50S22(:,1))/(m/3) sum(fp50x50S22(:,2))/(m/3) sum(fp50x50S22(:,3))/(m/3)]; fp50x50S22=0; fp50x50A2; m=size(fp50x50A2,2); fp50x50A22=reshape(fp50x50A2,m/3,3); fp50x50A2=[sum(fp50x50A22(:,1))/(m/3) sum(fp50x50A22(:,2))/(m/3) sum(fp50x50A22(:,3))/(m/3)]; fp50x50A22=0; m=size(ta50x50S1,2); ta50x50S12=reshape(ta50x50S1,m/6,6); ta50x50S1=[(sum(ta50x50S12(:,1))+sum(ta50x50S12(:,4)))/20 (sum(ta50x50S12(:,2))+sum(ta50x50S12(:,5)))/100 (sum(ta50x50S12(:,3))+sum(ta50x50S12(:,6)))/200]; ta50x50S12=0; m=size(ta50x50A1,2); ta50x50A12=reshape(ta50x50A1,m/6,6); ta50x50A1=[(sum(ta50x50A12(:,1))+sum(ta50x50A12(:,4)))/20 (sum(ta50x50A12(:,2))+sum(ta50x50A12(:,5)))/100 (sum(ta50x50A12(:,3))+sum(ta50x50A12(:,6)))/200]; ta50x50A12=0; m=size(ta50x50S2,2); ta50x50S22=reshape(ta50x50S2,m/3,3); ta50x50S2=[sum(ta50x50S22(:,1))/10 sum(ta50x50S22(:,2))/50 sum(ta50x50S22(:,3))/100]; ta50x50S22=0; ta50x50A2; m=size(ta50x50A2,2); ta50x50A22=reshape(ta50x50A2,m/3,3); ta50x50A2=[sum(ta50x50A22(:,1))/10 sum(ta50x50A22(:,2))/50 sum(ta50x50A22(:,3))/100]; ta50x50A22=0; 135 135 Estudio comparativo de modelos de identificación facial basados en correlación Fichero analizaFicheroPersona100x100.m: % % Fichero: analizaFicheroPersona100x100.m % Autor: Maria Sierra Zapata % Fecha: 01/07/2015 % Version: 0.1 % % Breve Descripcion: % Apertura de los ficheros generados debido a la % identificacion de personas para un modelo y con tamaño de imagen % 100x100 pixeles. Seleccion de los datos para la generacion de las % graficas para el estudio. % % Datos que se obtienen: % Tiempo Medio de Identificacion % Falsos Positivos Mujer % Falsos Positivos Hombre % Falsos Positivos % Tasa de Acierto Hombre % Tasa de Acierto Mujer % Tasa de Acierto % cadena='%d=%f %f %d'; num_images=[10 50 100]; % Apertura y lectura del fichero nom_fichero='100x100/ResultadosHombreM2_02.m'; dat=leeFicheroPersona(nom_fichero,cadena); % Obtencion de los datos del fichero [m,n]=size(dat); for i=1:m if i==1 if dat(i,2)==0 tmi100x100S1=0.0001; else tmi100x100S1=dat(i,2); end if dat(i,4)>5 fpm100x100S1=0; tah100x100S1=1; else fpm100x100S1=1; tah100x100S1=0; end if dat(i,4)==i+5 fp100x100S1=0; ta100x100S1=1; else fp100x100S1=1; ta100x100S1=0; end else if dat(i,2)==0 tmi100x100S1=[tmi100x100S1 0.0001]; else tmi100x100S1=[tmi100x100S1 dat(i,2)]; end if dat(i,4)>5 fpm100x100S1=[fpm100x100S1 0]; tah100x100S1=[tah100x100S1 1]; else fpm100x100S1=[fpm100x100S1 1]; tah100x100S1=[tah100x100S1 0]; end if dat(i,4)==i+5 fp100x100S1=[fp100x100S1 0]; ta100x100S1=[ta100x100S1 1]; else fp100x100S1=[fp100x100S1 1]; ta100x100S1=[ta100x100S1 0]; end end end nom_fichero='100x100/ResultadosMujerM2_02.m'; dat=leeFicheroPersona(nom_fichero,cadena);