sábado, 13 de noviembre de 2010
RETO VII: CONTAR CARAS
Para este reto vamos a ir probando distintas soluciones hasta dar con la más adecuada, lo que vamos a intentar hacer es contar caras, o sea cada vez que alguien pasa contarlo. Esto a priori parece fácil, pero si decimos cada vez que detectes cara, nos va a contar una por cada frame en la que aparece, con lo cual no tendría mucho sentido. Por lo tanto como primera aproximación vamos a intentar comparar imágenes si es la misma no la contamos si es una nueva la contamos. Si esto no funciona bien tendremos que intentar otras cosas, como intentar obtener los puntos biométricos de la cara y comparar, o seguir una imagen a lo largo de su trayectoria. De momento haremos esto para ver los resultados.
domingo, 7 de noviembre de 2010
SOLUCIÓN RETO VI: SEPARACIÓN DE LAS CARAS EN OTRAS IMAGENES
Para la resolución de este reto, me he creado una pequeña estructura, en la cual almaceno la imagen de la cara. La estructura es la siguiente:
Podemos ver que nuestra intención es realizar una lista con las caras, para he definido una serie de funciones para tratar esta lista.
int ListaVacia(Rostros R);
void Insertar(Rostros *R, IplImage* Cara);
Con estas funciones controlaremos la lista.
El código fuente de estas funciones será el siguiente.
Bueno pero, como separamos nuestra cara de la imagen. Para esto utilizaremos las siguientes funciones de OpenCV:
La primera, cvSetImageROI nos delimita la zona a copiar, la segunda función nos copia ese fragmento de imagen en la imagen des, y la tercera nos elimina la delimitación en la imagen, así la volvemos a tener completa otra vez.
Todo lo demás es exactamente igual al reto anterior.
El código fuente lo dejo aquí.
typedef struct _Rostro {
struct _Rostro* Anterior; // secuencia previa
struct _Rostro* Siguiente; // secuencia siguiente
struct _Rostro* Primero; //Primer elemento de la lista
int Nodo;
int total; // Número total de elementos
IplImage* Cara; //Aqui guardamos la cara
}Rostro;
typedef Rostro *pRostro;
typedef Rostro *Rostros;
struct _Rostro* Anterior; // secuencia previa
struct _Rostro* Siguiente; // secuencia siguiente
struct _Rostro* Primero; //Primer elemento de la lista
int Nodo;
int total; // Número total de elementos
IplImage* Cara; //Aqui guardamos la cara
}Rostro;
typedef Rostro *pRostro;
typedef Rostro *Rostros;
Podemos ver que nuestra intención es realizar una lista con las caras, para he definido una serie de funciones para tratar esta lista.
int ListaVacia(Rostros R);
void Insertar(Rostros *R, IplImage* Cara);
IplImage* MostrarRostro(Rostros *R,int nodo);
Con estas funciones controlaremos la lista.
El código fuente de estas funciones será el siguiente.
int ListaVacia(Rostros R) {
return (R == NULL);
}
void Insertar(Rostros *R, IplImage* Cara){
pRostro nuevo, anterior;
/* Crear un nodo nuevo */
nuevo = (pRostro)malloc(sizeof(Rostro));
nuevo->Cara= Cara;
if (ListaVacia(*R)){
*R=nuevo;
(*R)->Siguiente=NULL;
(*R)->Anterior=NULL;
(*R)->Cara=Cara;
(*R)->Nodo=0;
(*R)->total=1;
(*R)->Primero=*R;
}
else
{
anterior=(*R)->Primero;
while (anterior->Siguiente!=NULL){
anterior->total++;
anterior=anterior->Siguiente;
}
anterior->total++;
anterior->Siguiente=nuevo;
nuevo->Anterior=anterior;
nuevo->Siguiente=NULL;
nuevo->Nodo=anterior->Nodo+1;
nuevo->total=anterior->total;
nuevo->Cara=Cara;
}
}
IplImage* MostrarRostro(Rostros *R,int nodo){
pRostro Caras = *R;
if(ListaVacia(*R)) {
printf("ERROR: Lista Vacia\n");
return NULL;
}
else {
while(Caras->Nodo<nodo) {
Caras = Caras->Siguiente;
}
return Caras->Cara;
}
}
return (R == NULL);
}
void Insertar(Rostros *R, IplImage* Cara){
pRostro nuevo, anterior;
/* Crear un nodo nuevo */
nuevo = (pRostro)malloc(sizeof(Rostro));
nuevo->Cara= Cara;
if (ListaVacia(*R)){
*R=nuevo;
(*R)->Siguiente=NULL;
(*R)->Anterior=NULL;
(*R)->Cara=Cara;
(*R)->Nodo=0;
(*R)->total=1;
(*R)->Primero=*R;
}
else
{
anterior=(*R)->Primero;
while (anterior->Siguiente!=NULL){
anterior->total++;
anterior=anterior->Siguiente;
}
anterior->total++;
anterior->Siguiente=nuevo;
nuevo->Anterior=anterior;
nuevo->Siguiente=NULL;
nuevo->Nodo=anterior->Nodo+1;
nuevo->total=anterior->total;
nuevo->Cara=Cara;
}
}
IplImage* MostrarRostro(Rostros *R,int nodo){
pRostro Caras = *R;
if(ListaVacia(*R)) {
printf("ERROR: Lista Vacia\n");
return NULL;
}
else {
while(Caras->Nodo<nodo) {
Caras = Caras->Siguiente;
}
return Caras->Cara;
}
}
Bueno pero, como separamos nuestra cara de la imagen. Para esto utilizaremos las siguientes funciones de OpenCV:
cvSetImageROI(IplImage*,CvSeq);
cvCopy(IplImage* src,IplImage* des,NULL);
cvResetImageROI(IplImage*);
cvResetImageROI(IplImage*);
Todo lo demás es exactamente igual al reto anterior.
El código fuente lo dejo aquí.
#include "cv.h"
#include "highgui.h"
#include <iostream>
#include <cstdio>
#include <string>
#include "Funciones.h"
#include "Estructuras.h"
using namespace std;
void main()
{
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
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;
IplImage* RostroDetectado;
Rostros ListaRostros=NULL;
CvSeq* objects;
int i,j,k,l;
string nombreVentana;
cvSetCaptureProperty(capture,CV_CAP_PROP_FRAME_WIDTH,300);
cvSetCaptureProperty(capture,CV_CAP_PROP_FRAME_HEIGHT,300);
Frame=cvQueryFrame(capture); //Capturamos la primera imagen
if(Frame) //Si hay frame
{
gris = cvCreateImage( cvSize(Frame->width,Frame->height), 8, 1 );
while(1)
{
//Preparación de la imagen
cvCvtColor( Frame, gris, CV_BGR2GRAY );
//Capturamos el tiempo inicial
t = (double)cvGetTickCount();
objects= Deteccion_y_dibujo(gris, cascade, storage); //Aqui ya no me rellena el objects la segunda vez
//Capturamos el tiempo final y le restamos el inicial
t = (double)cvGetTickCount() - t;
//Dibujamos cuadros al rededor de los objetos
//Con lo cual este for no me lo hace
for( i = 0; i < (objects ? objects->total : 0); i++ ) {
CvRect* r = (CvRect*)cvGetSeqElem( objects, i );
cvRectangle(
Frame,
cvPoint(r->x,r->y),
cvPoint(r->x+r->width,r->y+r->height),
colores[i%8],
2
);
RostroDetectado = cvCreateImage(cvSize(r->width, r->height), gris->depth, gris->nChannels);
cvSetImageROI(gris,*r);
cvCopy(gris,RostroDetectado,NULL);
cvResetImageROI(gris);
Insertar(&ListaRostros, RostroDetectado);
}
//Visualizamos el tiempo
printf( "Tiempo deteccion = %g ms\n",t/((double) cvGetTickFrequency() *1000.) );
//Dibujamos la imagen
cvShowImage( "Imagen", Frame);
for( l = 0; l < (ListaRostros ? ListaRostros->total : 0); l++ )
{
nombreVentana="Imagen";
j=l;
do
{
k=j%10;
nombreVentana+=(char)(k+48);
j=j/10;
}
while (j/10!=0);
cvNamedWindow(nombreVentana.data(), CV_WINDOW_AUTOSIZE );
cvShowImage( nombreVentana.data(), MostrarRostro(&ListaRostros,l));
}
char c = cvWaitKey
if(c==27) break;
BorrarLista(&ListaRostros);
Frame=cvQueryFrame(capture); //Capturamos el resto de las imagenes
}
cvReleaseImage( &gris );
}
cvReleaseImage(&Frame);
CvSeq* Deteccion_y_dibujo( IplImage* gris,CvHaarClassifierCascade* cascade,CvMemStorage* storage )
{
CvSeq* objects;
cvEqualizeHist( gris, gris );
//Detección si las hay
cvClearMemStorage( storage );
objects = cvHaarDetectObjects(
gris,
cascade,
storage,
1.1,
2,
0 /*CV_HAAR_DO_CANNY_PRUNING*/,
cvSize(30, 30));
return objects;
}
#include "highgui.h"
#include <iostream>
#include <cstdio>
#include <string>
#include "Funciones.h"
#include "Estructuras.h"
using namespace std;
void main()
{
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
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;
IplImage* RostroDetectado;
Rostros ListaRostros=NULL;
CvSeq* objects;
int i,j,k,l;
string nombreVentana;
cvSetCaptureProperty(capture,CV_CAP_PROP_FRAME_WIDTH,300);
cvSetCaptureProperty(capture,CV_CAP_PROP_FRAME_HEIGHT,300);
Frame=cvQueryFrame(capture); //Capturamos la primera imagen
if(Frame) //Si hay frame
{
gris = cvCreateImage( cvSize(Frame->width,Frame->height), 8, 1 );
while(1)
{
//Preparación de la imagen
cvCvtColor( Frame, gris, CV_BGR2GRAY );
//Capturamos el tiempo inicial
t = (double)cvGetTickCount();
objects= Deteccion_y_dibujo(gris, cascade, storage); //Aqui ya no me rellena el objects la segunda vez
//Capturamos el tiempo final y le restamos el inicial
t = (double)cvGetTickCount() - t;
//Dibujamos cuadros al rededor de los objetos
//Con lo cual este for no me lo hace
for( i = 0; i < (objects ? objects->total : 0); i++ ) {
CvRect* r = (CvRect*)cvGetSeqElem( objects, i );
cvRectangle(
Frame,
cvPoint(r->x,r->y),
cvPoint(r->x+r->width,r->y+r->height),
colores[i%8],
2
);
RostroDetectado = cvCreateImage(cvSize(r->width, r->height), gris->depth, gris->nChannels);
cvSetImageROI(gris,*r);
cvCopy(gris,RostroDetectado,NULL);
cvResetImageROI(gris);
Insertar(&ListaRostros, RostroDetectado);
}
//Visualizamos el tiempo
printf( "Tiempo deteccion = %g ms\n",t/((double) cvGetTickFrequency() *1000.) );
//Dibujamos la imagen
cvShowImage( "Imagen", Frame);
for( l = 0; l < (ListaRostros ? ListaRostros->total : 0); l++ )
{
nombreVentana="Imagen";
j=l;
do
{
k=j%10;
nombreVentana+=(char)(k+48);
j=j/10;
}
while (j/10!=0);
cvNamedWindow(nombreVentana.data(), CV_WINDOW_AUTOSIZE );
cvShowImage( nombreVentana.data(), MostrarRostro(&ListaRostros,l));
}
char c = cvWaitKey
if(c==27) break;
BorrarLista(&ListaRostros);
Frame=cvQueryFrame(capture); //Capturamos el resto de las imagenes
}
cvReleaseImage( &gris );
}
cvReleaseImage(&Frame);
CvSeq* Deteccion_y_dibujo( IplImage* gris,CvHaarClassifierCascade* cascade,CvMemStorage* storage )
{
CvSeq* objects;
cvEqualizeHist( gris, gris );
//Detección si las hay
cvClearMemStorage( storage );
objects = cvHaarDetectObjects(
gris,
cascade,
storage,
1.1,
2,
0 /*CV_HAAR_DO_CANNY_PRUNING*/,
cvSize(30, 30));
return objects;
}
En este código se puede ver el empleo de la función
cvSetCaptureProperty(capture,CV_CAP_PROP_FRAME_WIDTH,300); la cual uso para cambiar el ancho del frame, y la función.
cvSetCaptureProperty(capture,CV_CAP_PROP_FRAME_HEIGHT,300); la cual utilizo para cambiar el alto, del frame.
Así de esta forma puedo llegar a un compromiso entre reconocimiento y velocidad de procesado.
Bueno como siempre si alguien tiene una solución mejor que la proponga, así aprendemos todos.
lunes, 1 de noviembre de 2010
RETO VI: SEPARACIÓN DE LAS CARAS EN OTRAS IMÁGENES
Muy buenas a todos, después de casi un mes desaparecido, vuelvo a escribir. Para este reto, propongo, coger el algoritmo de segmentación de caras y separar las caras en otras imágenes para posteriormente visualizarlas en la pantalla. De esta forma, ya podremos hacer lo que queramos con las caras. Reconocerlas, contarlas, lo que sea.
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
}
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 "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.
martes, 28 de septiembre de 2010
RETO V: SEGMENTACIÓN DE CARAS CON UNA CÁMARA
En este reto vamos a hacer lo mismo que en el reto IV pero esta vez empleando una cámara web. Segmentaremos las caras para posteriormente marcarlas en la imagen con un cuadrado.
Para hacer esto vamos a utilizar la función Deteccion_y_dibujo, modificandola para que nos diga también el tiempo que ha tardado en reconocer la cara. La función main la modificaremos para capturar las imágenes de la cámara web.
En principio parece un reto muy sencillo, ya que lo complicado está hecho.
domingo, 26 de septiembre de 2010
SOLUCIÓN RETO IV: SEGMENTACIÓN DE CARAS EN UNA IMAGEN
Muy buenas a todos, al final después de muchas búsquedas, he encontrado la solución a este reto. La solución es más fácil de lo que yo pensaba, ya que ya estaba hecha en OpenCV. Gracias al libro "Learnin OpenCV" de Gary Bradski y Adrian Kaehler, de la editorial O'reilly, lo he encontrado.
En OpenCV existe una función llamada cvHaarDetectObjects, que reconoce objetos utilizando el clasificador de Viola-Jones.
- Usa las características de entrada Haar-Like: un umbral aplicando sumas y restas de regiones rectangulares de la imagen.
- Es una técnica de integración de imagen que permite una rápida del valor de la región rectangular o regiones giradas 45º. Esta estructura de datos es utilizada para acelerar los cálculos de las características de las entradas.
- Se utiliza para crear una clasificación de las características por alta detección y débil rechazo.
- Esta organizado en un débil clasificador de nodos en una cascada de rechazos. En otras palabras, en el primer clasificador seleccionamos la mejor región detectada que contiene el objeto, permitiendo errores en la detección, en el siguiente nodo la segundo mejor detección. En un modo de test un objeto es detectado solo si ha superado toda la cascada de nodos.
Para utilizar esta función necesitamos entrenar la función cvHaarDetectObjects, en este reto no la hemos entrenado, lo dejamos para retos posteriores, ya que dentro del directorio data, de openCV encontramos el archivo haarcascade_frontalface_alt.xml que es el que he utilizado. Si es que al final OpenCV lo tiene todo resuelto, je je je.
A continuación dejo el código que he generado.
#include "cv.h"
#include "highgui.h"
#include <iostream>
#include <cstdio>
void Deteccion_y_dibujo( IplImage* imagen,CvHaarClassifierCascade* cascade,CvMemStorage* storage, double escala);
void main()
{
CvHaarClassifierCascade* cascade = (CvHaarClassifierCascade*)cvLoad( "haarcascade_frontalface_alt.xml",0, 0, 0 );
CvMemStorage* storage = cvCreateMemStorage(0);
IplImage* imagen = cvLoadImage("HPIM1403.jpg");
IplImage* imagenPequeña =cvCreateImage(cvSize((int)((imagen->width*25)/100) , (int)((imagen->height*25)/100) ),imagen->depth, imagen->nChannels );
cvResize(imagen,imagenPequeña,CV_INTER_NN);
Deteccion_y_dibujo(imagenPequeña, cascade, storage,1 );
//Creamos la ventana
cvNamedWindow( "Imagen", CV_WINDOW_AUTOSIZE );
//Dibujamos la imagen
cvShowImage( "Imagen", imagenPequeña);
cvWaitKey(0);
cvReleaseImage(&imagen);
}
void Deteccion_y_dibujo( IplImage* imagen,CvHaarClassifierCascade* cascade,CvMemStorage* storage, double escala )
{
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
IplImage* gris = cvCreateImage( cvSize(imagen->width,imagen->height), 8, 1 );
IplImage* Imagen_Pequeña = cvCreateImage(
cvSize( cvRound(imagen->width/escala), cvRound(imagen->height/escala)), 8, 1);
cvCvtColor( imagen, gris, CV_BGR2GRAY );
cvResize( gris, Imagen_Pequeña, CV_INTER_LINEAR );
cvEqualizeHist( Imagen_Pequeña, Imagen_Pequeña );
//Detección si las hay
cvClearMemStorage( storage );
CvSeq* objects = cvHaarDetectObjects(
Imagen_Pequeña,
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]
);
}
cvReleaseImage( &gris );
cvReleaseImage( &Imagen_Pequeña );
}
Aquí pongo unas fotografías en las que muestro los resultados.
Bueno, en los próximos días publicare el siguiente reto. Espero que no me cueste tanto como este je je je.
jueves, 16 de septiembre de 2010
RETO IV: SEGMENTACIÓN DE CARAS EN UNA IMAGEN
Hola a todos muy buenas, siento mucho haberme retrasado a la hora de escribir este nuevo reto. Para este reto vamos a intentar segmentar las caras de una fotografía, tal como hacen las cámaras de fotos, que para enfocar reconocen el lugar donde hay una cara. Bueno para esto buscaremos la posición de los ojos. De momento no puedo decir mucho, ya que solo he investigado un poquito el tema. Pero bueno, a ver si en una semana lo solucionamos entre todos.
Suscribirse a:
Entradas (Atom)

