El propósito del proyecto lideraado por zafersavas, y publicado en CodeProject es implementar un tiempo real eye tracker-función con las siguientes capacidades:
- Cara en tiempo real el seguimiento con la escala y la rotación invariante
- Seguimiento de las áreas de ojos individual
- Seguimiento características oculares
- Ojo dirección de la mirada hallazgo
- Control remoto mediante movimientos oculares
La segunda versión de TrackEye
soporta:
- Dos algoritmos de detección de rostros diferentes: Haar Face Tracking y CAMSHIFT
- Dos algoritmos de detección de ojos diferentes: Análisis de Componentes Principales Adaptativo y comparación de plantillas
- Algoritmos de seguimiento pueden ser seleccionados por el usuario al comienzo del proceso a través de GUI.
- Fuente de entrada seleccionable: Cámara Web o Archivo de vídeo
Tenga en cuenta que TrackEye
fue escrito con OpenCV
Biblioteca v3.1, así que asegúrese de usar durante la reconstrucción.
Instrucciones para ejecutar y reconstruir TrackEye
A continuación los links del ejecutable ,así como el codigo fuente para el seguimiento en tiempo real de los ojos humanos en las secuencias de vídeo de Interacción Persona-Ordenador utilizando una cámara web:- Descargar ejecutable – 2,51 MB
- Descargar el código fuente – 199.24 KB
Instrucciones De Instalación
- Extraer archivo TrackEye_Executable.zip. Antes de ejecutar TrackEye_636.exe, copie los dos archivosSampleHUE.jpg y SampleEye.jpg a la carpeta C: \. Estos dos archivos se utilizan para los algoritmos CAMSHIFT y Plantilla-juego.
- No hay otros pasos a seguir por el usuario para ejecutar el software. No hay dependencias DLL como el software fue construido con las DLL estáticamente incluidos.
Ajustes por hacer para realizar una buena Seguimiento
Ajustes de Detección de la cara y de los ojos
Bajo TrackEye Menú -> Configuración de Tracker
- Fuente de entrada: Video
- Haga clic en Seleccionar archivo y seleccionar .. \ Avis \ sample.avi
- Cara algoritmo de detección: Haar algoritmo de detección de rostros
- Marque “Track también Eyes” checkBox
- Ojo algoritmo de detección: Adaptativo PCA
- Desactive la opción “Comprobar Diferencia”
- Número de la base de datos de archivo: 8
- Número de EigenEyes: 5
- La distancia máxima permitida desde eyespace: 1200
- Rostro ancho / ojo anchura plantilla: 0.3
ColorSpace
tipo para utilizar durante PCA:CV_RGB2GRAY
Configuraciones para detección del Alumno
Compruebe “ojos de pista en los detalles” y luego seleccione “Detectar también pupilas”. Haga clic en el botón “Parámetros de Ajuste”:
- Introduzca “120” como el “Valor Umbral”
- Haga clic en “Guardar configuración” y luego haga clic en “Cerrar”
Ajustes para la serpiente
Marque “Indique ojo límite utilizando serpientes activos”. Haga clic en “Configuración de la serpiente” botón:
- Seleccione
ColorSpace
de usar:CV_RGB2GRAY
- Seleccione umbralización simple e introduzca 100 como el “Valor umbral”
- Haga clic en “Guardar configuración” y luego haga clic en “Cerrar”
Fondo
Hasta ahora no ha habido mucho trabajo en la detección de ojos y antes de que el proyecto, los métodos anteriores se estudiaron cuidadosamente para determinar el método aplicado. Podemos clasificar los estudios relacionados con el ojo en dos categorías principales que se enumeran a continuación:
Enfoques basados Equipo Especial
Este tipo de estudios de usar el equipo necesario que le dará una señal de algún tipo que es proporcional a la posición del ojo en la órbita. Varios métodos que están al día en uso son Electrooculografía, Infra-Rojo oculografía, esclerales bobinas de búsqueda. Estos métodos están completamente fuera de nuestro proyecto.
Imagen basada Enfoques
Los enfoques basados en la imagen realizan detecciones ojo en las imágenes. La mayoría de los métodos basados imagen tratar de detectar los ojos utilizando las características de los ojos. Los métodos utilizados hasta ahora son métodos basados en el conocimiento, los métodos basados en características (color, gradiente), sencilla comparación de plantillas, métodos de apariencia. Otro método interesante es “comparación de plantillas deformables”, que se basa en la coincidencia de una plantilla geométrica ojo en una imagen del ojo, reduciendo al mínimo la energía del modelo geométrico.
Implementación de TrackEye
El proyecto ejecutado es en tres componentes:
- Detección de rostros: Realiza la detección de rostros invariante escala
- La detección de los ojos: Ambos ojos se detectan como resultado de este paso
- Extracción de características de los ojos: Características de los ojos se extraen al final de este paso
Detección De Rostro
Dos métodos diferentes se llevaron a cabo en el proyecto. Ellos son:
- Continuamente adaptativos Medios-Shift Algoritmo
- Método de detección de la cara Haar
Algoritmo de continuamente adaptativo Mean-Shift
Adaptable Mean Shift algoritmo se utiliza para el seguimiento de rostros humanos y se basa en la técnica no paramétrica robusta para escalar gradientes de densidad de encontrar el modo (pico) de las distribuciones de probabilidad llamados el algoritmo medio turno. Como caras son rastreados en secuencias de vídeo, el algoritmo de cambio media se modifica para tratar con el problema de cambiar dinámicamente las distribuciones de probabilidad color. El diagrama de bloques del algoritmo se da a continuación:
Haar-Cara Método de detección
El segundo algoritmo de detección de cara se basa en un clasificador de trabajo con características Haar-gusta (a saber, una cascada de clasificadores impulsado de trabajo con características Haar-similares). Primero de todo, se entrenó con unos pocos cientos de puntos de vista de muestra de una cara. Después de un clasificador está entrenado, que puede ser aplicado a una región de interés en una imagen de entrada. El clasificador emite una “1
“si la región es probable que muestran la cara y” 0
“en caso contrario. Para buscar el objeto en toda la imagen, se puede mover la ventana de búsqueda a través de la imagen y comprobar cada ubicación utilizando el clasificador. El clasificador está diseñado de modo que pueda ser fácilmente “cambiar de tamaño” con el fin de ser capaz de encontrar los objetos de interés en diferentes tamaños, lo que es más eficiente que cambiar el tamaño de la imagen en sí.
Detección de ojos
Dos métodos diferentes se llevaron a cabo en el proyecto:
- Plantilla de emparejamiento
- Adaptable
EigenEye
Método
Plantilla de emparejamiento
Plantilla-Matching es un método bien conocido para la detección de objetos. En nuestro método de correspondencia de plantilla, se crea un patrón de ojo norma manualmente y se le dio una imagen de entrada, los valores de correlación con los patrones estándar se calculan para los ojos. La existencia de un ojo se determina basándose en los valores de correlación. Este enfoque tiene la ventaja de ser simple de implementar.Sin embargo, a veces puede ser inadecuada para la detección del ojo ya que no puede tratar eficazmente con la variación en escala, pose y forma.
Método Adaptativo EigenEye
Adaptable EigenEye
método se basa en el método conocidos EigenFaces
. Sin embargo, como el método se utiliza para la detección de ojos lo nombramos como ” EigenEye
Método “. La idea principal es descomponer imágenes del ojo en un pequeño conjunto de características incluyen imágenes llamadas eigeneyes, que pueden ser considerados como los principales componentes de las imágenes originales. Estos eigeneyes funcionan como los vectores de la base ortogonal de un subespacio llamados eyespace. Sin embargo, sabemos que laeigenface
método no es escalar invariante. Para proporcionar la invariancia de escala podemos cambiar el tamaño de la base de datos de los ojos una vez con la información obtenida por el algoritmo de detección de rostros ( EyeWidth / FaceWidth ? 0 . 35
), podemos proporcionar una detección escala invariante utilizando sólo una base de datos.
Funciones OpenCV para el seguimiento de objetos y detección
OpenCV
Biblioteca ofrece una gran cantidad de procesamiento de imágenes y de seguimiento de objetos y detección de bibliotecas. La función principal que se utiliza en estos proyectos y su uso se indican a continuación:
Código de ejemplo para el seguimiento Haar-Cara
Ocultar Shrink Código Copiaranular CTrackEyeDlg :: HaarFaceDetect (IplImage * img, CvBox2D * Facebox) { int escala = 2; IplImage * temp = cvCreateImage (cvSize (img-> ancho / 2, img-> Altura / 2), 8, 3); Pt1 CvPoint, pt2; int i; cvPyrDown (img, temperatura, CV_GAUSSIAN_5x5); WIN32 #ifdef cvFlip (temp, temp, 0); #terminara si cvClearMemStorage (almacenamiento); si (hid_cascade) { CvSeq * enfrenta = cvHaarDetectObjects (temp, hid_cascade, almacenamiento, 1. 2, 2, CV_HAAR_DO_CANNY_PRUNING); NumOfHaarFaces = faces-> total; si (NumOfHaarFaces> 0) { CvRect * r = (CvRect *) cvGetSeqElem (caras, 0, 0); pt1.x = r-> x * escala; pt2.x = (r-> x + r> ancho) * escala; WIN32 #ifdef pt1.y = img-> Altura - r-> escala y *; pt2.y = img-> Altura - (r> y + r> altura) * escala; #else pt1.y = r-> escala y *; pt2.y = (r> y + r> altura) * escala; #terminara si faceBox-> center.x = (float) (pt1.x + pt2.x) / 2 0.; faceBox-> center.y = (float) (pt1.y + pt2.y) / 2; faceBox-> Tamano.Width = (float) (pt2.x - pt1.x); faceBox-> size.height = (float) (pt1.y - pt2.y); } } cvShowImage ("Seguimiento", img); cvReleaseImage (y temporal); }
Código de ejemplo para CamShift Algoritmo
Ocultar Código Copiar// Las entradas para el algoritmo CamShift IplImage * HUE = cvCreateImage (cvGetSize (SampleForHUE), IPL_DEPTH_8U, 1); extractHUE (SampleForHUE, HUE); // ** información HUE Extracto int hist_size = 20; flotar rangos [] = {0, 180}; flotar * pranges [] = {} rangos; hist = cvCreateHist (1, y hist_size, CV_HIST_ARRAY, pranges, 1); cvCalcHist (y HUE, hist); // Calcular el histograma de una parte HUE hueFrame = cvCreateImage (cvGetSize (CameraFrame), IPL_DEPTH_8U, 1); backProject = cvCreateImage (cvGetSize (CameraFrame), IPL_DEPTH_8U, 1); extractHUE (CameraFrame, hueFrame); while (trackCONTROL! = 0) { extractHUE (CameraFrame, hueFrame); cvCalcBackProject (y hueFrame, backProject, hist); se forma // Probabilidad // CvShowImage ("Tester2", backProject); cvCamShift (backProject, SearchWin, cvTermCriteria (CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 15, 0 1), y un borrador, y Facebox).; SearchWin = comp.rect; }
Muestra Matching Plantilla Código
Ocultar Shrink Código Copiar// Coincidencia Plantilla para la detección de ojos void Cara :: findEyes_TM (IplImage * faceImage, TrackingSettings * Ajustes) { CvSize faceSize; faceSize = cvGetSize (faceImage); // Cargar plantilla de la base de datos de ojo CString nomArchivo; // Nombre de la plantilla para el ojo izquierdo fileName.Format ("% s \\% d.jpg ojo", Preferencias-> params-> DBdirectory, 0); IplImage * eyeImage_Left = cvLoadImage (nomArchivo, - 1); // Nombre de la plantilla para el ojo izquierdo fileName.Format ("% s \\% d.jpg ojo", Preferencias-> params-> DBdirectory, 1); IplImage * eyeImage_Right = cvLoadImage (nomArchivo, - 1); IplImage * tempTemplateImg_Left; IplImage * tempTemplateImg_Right; IplImage * templateImg_Left; IplImage * templateImg_Right; si (eyeImage_Left == NULL || eyeImage_Right == NULL) { MessageBox (NULL, "plantillas no pueden ser cargados. \ N Por favor revise su carpeta de ojo de base de datos "," Error ", MB_OK || MB_ICONSTOP); exit (1); } más { // Espacio Cambiar el color de acuerdo a los ajustes introducidos por el usuario tempTemplateImg_Left = cvCreateImage (cvGetSize (eyeImage_Left), IPL_DEPTH_8U, 1); changeColorSpace (ajustes, eyeImage_Left, tempTemplateImg_Left); tempTemplateImg_Right = cvCreateImage (cvGetSize (eyeImage_Right), IPL_DEPTH_8U, 1); changeColorSpace (ajustes, eyeImage_Right, tempTemplateImg_Right); flotar idealWidth = faceSize.width * Preferencias-> params-> relación; flotar conversionRatio = idealWidth / (float) tempTemplateImg_Left-> ancho; CvSize newSize; newSize.width = (int) idealWidth; newSize.height = (int) (tempTemplateImg_Left-> Altura * conversionRatio); templateImg_Left = cvCreateImage (newSize, IPL_DEPTH_8U, 1); cvResize (tempTemplateImg_Left, templateImg_Left, CV_INTER_LINEAR); // era NN cvReleaseImage (y eyeImage_Left); cvReleaseImage (y tempTemplateImg_Left); templateImg_Right = cvCreateImage (newSize, IPL_DEPTH_8U, 1); cvResize (tempTemplateImg_Right, templateImg_Right, CV_INTER_LINEAR); // era NN cvReleaseImage (y eyeImage_Right); cvReleaseImage (y tempTemplateImg_Right); } // ************************************************ ************* // ************ Buscar faceImage para los ojos ************************ // ************************************************ ************* IplImage * GRAYfaceImage = cvCreateImage (faceSize, IPL_DEPTH_8U, 1); changeColorSpace (ajustes, faceImage, GRAYfaceImage); // CvCvtColor (faceImage, GRAYfaceImage, CV_RGB2GRAY); // GRAYfaceImage-> origen = 1; // ** Aviso a este origen imagen punto es la esquina inferior izquierda. // ** Área de búsqueda Eye1 int x_left = 0; int y_left = 0; int width_left = (int) ((float) (faceSize.width / 2 0).); int height_left = (int) ((float) (faceSize.height)); CvRect rect_Eye1 = cvRect (x_left, y_left, width_left, height_left); CvMat * Eye1Image = cvCreateMat (width_left, height_left, CV_8UC1); cvGetSubRect (GRAYfaceImage, Eye1Image, rect_Eye1); cvFlip (Eye1Image, Eye1Image, 0); // ** Área de búsqueda Eye2 int x_right = (int) ((float) (faceSize.width / 2 0).); int y_right = 0; int width_right = (int) ((float) (faceSize.width / 2 0).); int height_right = (int) ((float) (faceSize.height)); CvRect rect_Eye2 = cvRect (x_right, y_right, width_right, height_right); CvMat * Eye2Image = cvCreateMat (width_right, height_right, CV_8UC1); cvGetSubRect (GRAYfaceImage, Eye2Image, rect_Eye2); cvFlip (Eye2Image, Eye2Image, 0); // OpenCV dice que el tamaño del resultado debe ser el siguiente: Tamaño CvSize; size.height = Eye1Image-> Altura - templateImg_Left-> alto + 1; Tamano.Width = Eye1Image-> Ancho - templateImg_Left-> ancho + 1; IplImage * resultado1 = cvCreateImage (tamaño, IPL_DEPTH_32F, 1); IplImage * result2 = cvCreateImage (tamaño, IPL_DEPTH_32F, 1); // Ojo Izquierdo cvMatchTemplate (Eye1Image, templateImg_Left, resultado1, Preferencias-> params-> tempMatch); // Ojo Derecho cvMatchTemplate (Eye2Image, templateImg_Right, result2, Preferencias-> params-> tempMatch); // Encontrar la mejor ubicación partido - OJO IZQUIERDO doble minValue1, maxValue1; CvPoint minLoc1, maxLoc1; cvMinMaxLoc (resultado1, y minValue1, y maxValue1, y minLoc1, y maxLoc1); cvCircle (resultado1, maxLoc1, 5, Preferencias-> programColors.colors [2], 1); // Transformar punto de volver a la imagen original maxLoc1.x + = templateImg_Left-> Ancho / 2; maxLoc1.y + = templateImg_Left-> Altura / 2; Preferencias-> params-> eye1.coords.x = maxLoc1.x; Preferencias-> params-> eye1.coords.y = maxLoc1.y; Preferencias-> params-> eye1.RectSize.width = templateImg_Left-> ancho; Preferencias-> params-> eye1.RectSize.height = templateImg_Left-> altura; Preferencias-> params-> eye1.eyefound = true; // Encontrar la mejor ubicación partido - Ojo Derecho doble minValue2, maxValue2; CvPoint minLoc2, maxLoc2; cvMinMaxLoc (result2, y minValue2, y maxValue2, y minLoc2, y maxLoc2); cvCircle (result2, maxLoc2, 5, Preferencias-> programColors.colors [2], 1); // Transformar punto de volver a la imagen original maxLoc2.x + = templateImg_Left-> Ancho / 2; maxLoc2.y + = templateImg_Left-> Altura / 2; Preferencias-> params-> eye2.coords.x = maxLoc2.x + (int) faceSize.width / 2; Preferencias-> params-> eye2.coords.y = maxLoc2.y; Preferencias-> params-> eye2.RectSize.width = templateImg_Left-> ancho; Preferencias-> params-> eye2.RectSize.height = templateImg_Left-> altura; Preferencias-> params-> eye2.eyefound = true; cvCircle (Eye1Image, maxLoc1, 5, Preferencias-> programColors.colors [2], 1); cvCircle (Eye2Image, maxLoc2, 5, Preferencias-> programColors.colors [2], 1); }
Código de ejemplo de adaptación Método EigenEye
Ocultar Shrink Código CopiarCara void :: findEyes (IplImage * faceImage, TrackingSettings * Ajustes) { IplImage ** imágenes = (IplImage **) malloc (sizeof (IplImage *) * numOfImages); IplImage ** eigens = (IplImage **) malloc (sizeof (IplImage *) * numOfImages); IplImage * averageImage; IplImage * proyección; CvSize faceSize; faceSize = cvGetSize (faceImage); eigenSize newEigenSize; newEigenSize.width = faceSize.width * Preferencias-> params-> relación; newEigenSize.conversion = ((float) newEigenSize.width) / ((float) base de datos [0] -> ancho); newEigenSize.height = ((float) base de datos [0] -> altura) * newEigenSize.conversion; CvSize newSize; newSize.width = (int) newEigenSize.width; newSize.height = (int) newEigenSize.height; IplImage * tempImg = cvCreateImage (newSize, IPL_DEPTH_8U, 1); // ********** ********** Inicializaciones for (int i = 0; i <Preferencias- /> params-> nImages; i ++) { imágenes [i] = cvCreateImage (newSize, IPL_DEPTH_8U, 1); cvResize (base de datos [i], imágenes [i], CV_INTER_LINEAR); // era NN } cvShowImage ("eigen", imágenes [0]); cvReleaseImage (y tempImg); // Crear el espacio para Eigenfaces for (i = 0; i <Preferencias- /> params-> nImages; i ++) eigens [i] = cvCreateImage (cvGetSize (imágenes [0]), IPL_DEPTH_32F, 1); averageImage = cvCreateImage (cvGetSize (imágenes [0]), IPL_DEPTH_32F, 1); proyección = cvCreateImage (cvGetSize (imágenes [0]), IPL_DEPTH_8U, 1); // ************************************************ ************* // ************ Calcula los vectores propios y valores propios ************* // ************************************************ ************* Criterios CvTermCriteria; criteria.type = CV_TERMCRIT_ITER | CV_TERMCRIT_EPS; criteria.maxIter = 13; criteria.epsilon = 0. 1; // ** N estaba presente en lugar de numOfImages cvCalcEigenObjects (Preferencias-> params-> nImages, imágenes, eigens, 0, 0, 0, y criterios, averageImage, vals); // ************************************************ ************* // ************ Buscar faceImage para los ojos ************************ // ************************************************ ************* IplImage * GRAYfaceImage = cvCreateImage (faceSize, IPL_DEPTH_8U, 1); changeColorSpace (ajustes, faceImage, GRAYfaceImage); // CvCvtColor (faceImage, GRAYfaceImage, CV_RGB2GRAY); // ** Aviso a este origen imagen punto es la esquina inferior izquierda. GRAYfaceImage-> origen = 1; int MARGEN = Preferencias-> params-> MAXERROR; doble mínimo = MARGEN; doble distancia = MARGEN; // ** Búsqueda Eye1 Espacio Preferencias-> params-> eye1.xlimitLeft = 0; Preferencias-> params-> eye1.xlimitRight = faceSize.width / 2 0 - imágenes [0] -> ancho -. 1; Preferencias-> params-> eye1.ylimitUp = (Int) (((float) faceSize.height) * 0 - 75 imágenes [0] -> Altura - 1.); Preferencias-> params-> eye1.ylimitDown = faceSize.height / 2; // ** Búsqueda Eye2 Espacio . Preferencias-> params-> eye2.xlimitLeft = faceSize.width / 2 0; Preferencias-> params-> eye2.xlimitRight = faceSize.width - imágenes [0] -> Ancho - 1; Preferencias-> params-> eye2.ylimitUp = (Int) (((float) faceSize.height) * 0 - 75 imágenes [0] -> Altura - 1.); Preferencias-> params-> eye2.ylimitDown = faceSize.height / 2; Preferencias-> params-> eye1.initializeEyeParameters (); Preferencias-> params-> eye2.initializeEyeParameters (); Preferencias-> params-> eye1.RectSize.width = imágenes [0] -> anchura; Preferencias-> params-> eye1.RectSize.height = imágenes [0] -> altura; Preferencias-> params-> eye2.RectSize.width = imágenes [0] -> anchura; Preferencias-> params-> eye2.RectSize.height = imágenes [0] -> altura; IplImage * Image2Comp = cvCreateImage (cvGetSize (imágenes [0]), IPL_DEPTH_8U, 1); int x, y; // ** Buscar ojo izquierdo es decir eye1 for (y = Preferencias-> params-> eye1.ylimitDown; y <Preferencias- />params->eye1.ylimitUp; y + = 2) { for (x = Preferencias-> params-> eye1.xlimitLeft; x <Preferencias- />params->eye1.xlimitRight; x + = 2) { cvSetImageROI (GRAYfaceImage, cvRect (x, y, imágenes [0] -> anchura, imágenes [0] -> altura)); si (Preferencias-> params-> varianceCheck == 1) { si (calculateSTD (GRAYfaceImage) <= (doble) (Preferencias-> params-> varianza)) { cvResetImageROI (GRAYfaceImage); continuar; } } cvFlip (GRAYfaceImage, Image2Comp, 0); cvResetImageROI (GRAYfaceImage); // Decidir si se trata de un ojo o no cvEigenDecomposite (Image2Comp, Preferencias-> params-> nEigens, eigens, 0, 0, averageImage, pesos); cvEigenProjection (eigens, Preferencias-> params-> nEigens, CV_EIGOBJ_NO_CALLBACK, 0, pesos, averageImage, proyección); distancia = cvNorm (Image2Comp, proyección, CV_L2, 0); si (distancia <& distancia mínima> 0) { Preferencias-> params-> eye1.eyefound = true; mínimo = distancia; Preferencias-> params-> eye1.distance = distancia; Preferencias-> params-> eye1.coords.x = x; Preferencias-> params-> eye1.coords.y = y; } } } mínimo = MARGEN; distancia = MARGEN; // ** Buscar ojo derecho es decir eye2 for (y = Preferencias-> params-> eye2.ylimitDown; y <Preferencias- />params->eye2.ylimitUp; y + = 2) { for (x = Preferencias-> params-> eye2.xlimitLeft; x <Preferencias- />params->eye2.xlimitRight; x + = 2) { cvSetImageROI (GRAYfaceImage, cvRect (x, y, imágenes [0] -> anchura, imágenes [0] -> altura)); si (Preferencias-> params-> varianceCheck == 1) { si (calculateSTD (GRAYfaceImage) <= (doble) (Preferencias-> params-> varianza)) { cvResetImageROI (GRAYfaceImage); continuar; } } cvFlip (GRAYfaceImage, Image2Comp, 0); cvResetImageROI (GRAYfaceImage); // ** Decidir si se trata de un ojo o no cvEigenDecomposite (Image2Comp, Preferencias-> params-> nEigens, eigens, 0, 0, averageImage, pesos); cvEigenProjection (eigens, Preferencias-> params-> nEigens, 0, 0, pesos, averageImage, proyección); distancia = cvNorm (Image2Comp, proyección, CV_L2, 0); si (distancia <& distancia mínima> 0) { Preferencias-> params-> eye2.eyefound = true; mínimo = distancia; Preferencias-> params-> eye2.distance = distancia; Preferencias-> params-> eye2.coords.x = x; Preferencias-> params-> eye2.coords.y = y; } } } cvReleaseImage (y Image2Comp); // ** Limpiar cvReleaseImage (y GRAYfaceImage); for (i = 0; i <Preferencias- /> params-> nImages; i ++) cvReleaseImage (e imágenes [i]); for (i = 0; i <Preferencias- /> params-> nImages; i ++) cvReleaseImage (y eigens [i]); cvReleaseImage (y averageImage); cvReleaseImage (y proyección); libres (imágenes); libres (eigens); } Licencia:Este traduccción del artículo, junto con cualquier código y archivos fuente asociado, está licenciado bajo la licencia de código abierto del proyecto (CPOL)
Fuente aqui