viernes, 8 de octubre de 2010

SOLUCIÓN RETO V: SEGMENTACIÓN DE CARAS CON UNA CÁMARA

La solución a este reto es muy similar a la del reto anterior, seguiremos utilizando la función cvHaarDetectObjects de la misma manera que en el reto anterior.  La diferencia es que en este utilizamos una cámara, o sea que estamos reconociendo las caras en un montón de fotografías, una detrás de otra.  Esta función devuelve una secuencia, que es donde se encuentran las caras, esta secuencia es del tipo CvSeq, que es una estructura definida de este tipo:
typedef struct CvSeq {
    int flags; // misceláneo de banderas
    int header_size; // Tamaño y secuencia de la cabecera
    CvSeq* h_prev; // secuencia previa
    CvSeq* h_next; // secuencia siguiente
    CvSeq* v_prev; // Previsión de las secuencia 2n
    CvSeq* v_next // Previsión de la secuancia 2n siguiente
    int total; // Número total de elementos
    int elem_size; // Tamaño de la secuencia en byte
    char* block_max; // Máximo contorno en el último bloquie
    char* ptr; // Puntero de escritura actual
    int delta_elems; // Cuantos punteros asignados cuando la secuencia crece
    CvMemStorage* storage; //Cuando la secuencia es almacenada
    CvSeqBlock* free_blocks; // Lista libre de bloques
    CvSeqBlock* first; // Puntero al primer elemnto de bloque
}
Los parámetros de entrada de esta función son los siguientes; la imagen en tonalidad de grises, un puntero a un dato de tipo  CvHaarClassifierCascade* que no es nada más que el archivo donde están los parámetros de reconocimiento, un parámetro del tip CvMemStorage* que es una especie de almacén, más adelante explicaré este elemento, cuando lo entienda mejor je je je, el factor de escala, el número de vecinos, unas banderas y el tamaño mínimo.  
Lo que hace esta función ya lo esplique un poco por encima en el reto 4, tampoco vamos a entrar en muchos detalles, hay mucha más información en el libro learning openCV, lo malo que esta en ingles, pero es muy simple de leer.
Como siempre os dejo mi código, más adelante iremos profundizando un poco más.  Cuando vaya yo aprendiendo, je je je.


#include "cv.h"
#include "highgui.h"

#include <iostream>
#include <cstdio>

void Deteccion_y_dibujo( IplImage* imagen,IplImage* gris,CvHaarClassifierCascade* cascade,CvMemStorage* storage);

void main()
{
     double t;
     bool Primera= true;
     CvHaarClassifierCascade* cascade = (CvHaarClassifierCascade*)cvLoad( "haarcascade_frontalface_alt.xml",0, 0, 0 );
     CvMemStorage* storage = cvCreateMemStorage(0);
     //Creamos la ventana
     cvNamedWindow( "Imagen", CV_WINDOW_AUTOSIZE );
     //Capturamos la cámara
     CvCapture* capture= cvCreateCameraCapture(0);   
     assert( capture != NULL ); 
     IplImage* Frame;
     IplImage* gris

     while(1)
     {
        Frame=cvQueryFrame(capture);  //Capturamos la primera imagen
        if(!Frame) break;  //Si no hay frame salimos
        if (Primera)
        {
            gris = cvCreateImage( cvSize(Frame->width,Frame->height), 8, 1 );
            Primera= false;
        }

        //Capturamos el tiempo inicial
        t = (double)cvGetTickCount();
        Deteccion_y_dibujo(Frame,gris, cascade, storage);
        //Capturamos el tiempo final y le restamos el inicial
        t = (double)cvGetTickCount() - t;
        //Visualizamos el tiempo
        printf( "Tiempo deteccion = %g ms\n", t/((double)cvGetTickFrequency()*1000.) );
        //Dibujamos la imagen
        cvShowImage( "Imagen", Frame);
   
        char c = cvWaitKey(33);
        if(c==27) break;
     }
     cvReleaseImage(&Frame);
     cvReleaseImage( &gris );

  
}

void Deteccion_y_dibujo( IplImage* imagen,IplImage* gris,CvHaarClassifierCascade* cascade,CvMemStorage* storage  )
{
     static CvScalar colores[] = {
        {{0,0,255}}, {{0,128,255}},{{0,255,255}},{{0,255,0}},
        {{255,128,0}},{{255,255,0}},{{255,0,0}}, {{255,0,255}}};//Colores para dibujar
   
     //Preparación de la imagen
     cvCvtColor( imagen, gris, CV_BGR2GRAY );
     cvEqualizeHist( gris, gris );
   
     //Detección si las hay
     cvClearMemStorage( storage );
     CvSeq* objects = cvHaarDetectObjects(
            gris,
            cascade,
            storage,
            1.1,
            2,
            0 /*CV_HAAR_DO_CANNY_PRUNING*/,
            cvSize(30, 30));
     //Dibujamos cuadros al rededor de los objetos
     for(int i = 0; i < (objects ? objects->total : 0); i++ ) {
            CvRect* r = (CvRect*)cvGetSeqElem( objects, i );
            cvRectangle(
            imagen,
            cvPoint(r->x,r->y),
            cvPoint(r->x+r->width,r->y+r->height),
            colores[i%8],
            2
            );
     }
   
}


También os dejo un video.

No hay comentarios:

Publicar un comentario