TrackEye: Seguimiento en tiempo real de los ojos humanos utilizando una cámara web


 Los ojos son las características más importantes de la cara humana,así que el uso eficaz de los movimientos de los ojos como una técnica de comunicación en las interfaces de usuario a la computadora puede encontrar lugar en diversas áreas de aplicación.El seguimiento de los ojos y la información proporcionada por las características de los ojos tienen el potencial de convertirse en una interesante manera de comunicarse con un ordenador en un sistema de interacción persona-ordenador (HCI). Así que con esta motivación, el diseño de un software en tiempo real de seguimiento característica del ojo es el objetivo de este proyecto.

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

  1. 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.
  2. 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:

  1. Detección de rostros: Realiza la detección de rostros invariante escala
  2. La detección de los ojos: Ambos ojos se detectan como resultado de este paso
  3. 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:

  1. Continuamente adaptativos Medios-Shift Algoritmo
  2. 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:

Camshift Algoritmo

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:

  1. Plantilla de emparejamiento
  2. 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

  anular 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

  // 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

  // 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

  Cara 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

Cómo leer el pensamiento


 La última tendencia en los juguetes? La biorretroalimentación y la electroencefalografía. Una década en el siglo XXI, el mercado de los juguetes está inundado de productos que incorporan sensores neuronales funcionales,como   por ejemplo  Milton Star Wars Fuerza Trainer (~ $ 80), un juguete que desafía a los jugadores para hacer levitar una pelota de ping-pong.

HowTo: Leer tu propia mente

Otro ejemplo es el juguete de Mattel Mindflex (~ $ 75).

HowTo: Leer tu propia mente

Ambos productos licencia de su tecnología EEG de NeuroSky, una empresa que también vende su propia interfaz cerebro-ordenador de grado de investigación, el modo de pensar ($ 200). Lo que la comunidad hacker ha descubierto, sin embargo, es que, con un poco de retoques, los $ 75 dólares Mindflex puede hacerse a comportarse muy parecido a su contraparte más cara.

Las instrucciones completas siguen a continuación :https://vimeo.com/10184668

Necesitará:

  • 1 x Mindflex
  • 3 pilas AAA para el auricular
  • 1 x Arduino (cualquier variedad), con cable USB
  • 2 x 12 «longitudes de cable de conexión de núcleo sólido (alrededor de # 22 o # calibre 24 es el mejor).
  • Un PC o Mac para controlar los datos en serie
  • Arduino cerebro Biblioteca (descarga aquí)
  • Opcional: procesamiento cerebral Visualizer (descarga aquí, que le ayudará a tener Procesamiento también)
  • Opcional (necesario para el visualizador): controlP5 Procesamiento GUI Library (descarga aquí)

Paso 1 Desmontar el auricular Mind Flex.

Coja un destornillador y abra una grieta en la vaina izquierda del auricular Mind Flex. (La vaina derecha sostiene las baterías.)

HowTo: Leer tu propia mente

Paso 2 Soldar un trozo de alambre al pin «T».

La Junta NeuroSky es la pequeña tarjeta hija hacia la parte inferior del audífono.Si se fija bien, debería ver convenientemente etiquetado T y R pines – estas son las clavijas del tablero EEG utiliza para comunicarse en serie al microcontrolador en la placa principal, y son los pines que usaremos para espiar a los datos del cerebro . Soldar un trozo de alambre (con cuidado) a la patilla «T». Alambre fino está bien, usamos # calibre 24. Sea cuidadoso para no cortar las patillas vecinas.

Paso 3 Planta él.

Su Arduino querrá compartir terreno con el circuito Mind Flex. Soldar otra longitud de cable a tierra – cualquier punto de tierra va a hacer, pero el uso de la gran plataforma de la soldadura en la conexión a tierra de la batería llega a la junta hace el trabajo más fácil. Una nota sobre el poder: Hemos encontrado la Mente Flex sea excesivamente sensible al poder … nuestra esperanza inicial era para alimentar el tablero de NeuroSky de alimentación 3.3v del Arduino, pero esto resultó poco fiable. Por ahora estamos pegando con la configuración de fábrica y encender el Arduino y Mente Flex independiente.

HowTo: Leer tu propia mente

Paso 4 Pase los cables.

Usamos una gota de pegamento caliente para actuar como alivio de tensión para los nuevos cables y perforamos un agujero en el caso de los dos cables que asoman a través después de que el caso fue cerrado. Este paso es opcional.

Paso 5 Conecte el Arduino.

El cable del pin «T» de la Mente Flex entra en pin RX del Arduino. La planta va … a tierra. Si lo desea, para asegurar el Arduino a un lado de la Mente Flex como una cuestión de conveniencia. (Utilizamos bridas.

HowTo: Leer tu propia mente

Paso 6 Cargue el Arduino.

Descargar e instalar el cerebro Biblioteca Arduino – está disponible aquí. Abra el ejemplo BrainSerialOut y subirlo a su tablero. (Es posible que tenga que desconectar el pin RX durante la carga.) El código de ejemplo se ve así:

HowTo: Leer tu propia mente

Paso 7 Probar.

A su vez en la mente Flex, asegúrese de que el Arduino está conectado al ordenador, y luego abrir el Serial Monitor. Si todo ha ido bien, debería ver lo siguiente:

Así es como la CSV se rompe: «intensidad de la señal, la atención, la meditación, delta, theta, alfa baja, alta alfa, beta baja, alta beta, gamma de baja y de alta gamma»

(Más de lo que se supone que estos valores en el sentido de adelante en el artículo Además, tenga en cuenta que si están cortando un entrenador Fuerza en lugar de una Mente Flex, sólo verá los tres primeros valores -.. Señal de fuerza, de atención y de meditación)

Si coloca la unidad sobre su cabeza, usted debe ver el valor «intensidad de la señal» gota a 0 (confusamente, esto significa que la conexión es buena), y el resto de los números comienzan a fluctuar.

HowTo: Leer tu propia mente

Paso 8 Visualizar.

Tan emocionante como el monitor de serie es, se podría pensar, «Seguramente hay una manera más intuitiva de visualizar estos datos!» Está de suerte: al autor ha  escrito un visualizador rápido, de código abierto en el procesamiento que representa gráficamente la actividad de su cerebro sobre tiempo (descargar).Está diseñado para trabajar con el código BrainSerialOut de Arduino ya  cargado.

Descargar el código, a continuación, abra el archivo brain_grapher.pde en Processing. Con la mente Flex conectado a través de USB y encendido, seguir adelante y ejecutar el boceto de procesamiento. (Sólo asegúrese de que el monitor de serie el Arduino IDE ‘s es cerrado, de lo contrario Procesamiento no será capaz de leer la mente de Flex.) Puede que tenga que cambiar el índice de la lista de arreglo de serie en el archivo brain_grapher.pde, en caso de Arduino no es el primer objeto de serie de su máquina:

serie = nueva serie (esto, Serial.list () [0], 9600);

Usted debe terminar con una pantalla como esta:

HowTo: Leer tu propia mente

 

Fuente aqui