Para mejorar las posibilidades de la detección de cuadrados en busca de la carátula de CD me he aventurado a probar la sustracción de fondo.

Considero que la cámara va a estar colocada en un sitio concreto. Incluso me estoy planteando enfocarla hacia arriba. Pero eso es facilitarme las cosas demasiado. Primero quiero ver las carátulas y después ir subiendo la complejidad. Es posible que cada vez que suba un nivel de complejidad el enfoque para llegar a la solución sea diferente. Pero lo importante es aprender :) Acepto críticas y sugerencias. (De sabios es evaluar y dudar cuidadosamente cualquier afirmación).

Con este enfoque pretendo quedarme con lo que se mueva y a partir de ahí pasar el detector de cuadrados.

En el código que estoy utilizando:

  • Es un refrito, hay partes en castellano y otras en ingles. ¡ Son pruebas !
  • Se está realizando una sustracción del fondo Gausiana (Gaussian Mixture Model)
  • Se genera un mapa de bits donde el negro absoluto significa fondo y el blanco puro significa “no fondo” ( es decir, algo en movimiento)
  • En la ventana llamada “Original” genero una imagen en la que solo se ve lo que está en movimiento.
  • Tiene un warning en la asignación de valor a x, insisto! son pruebas!

backgrsub

Enlaces de interés:

Código:

#include "cv.h"
#include "cvaux.h"
#include "highgui.h"
#include <stdio.h>

const CvScalar C_RGB_BLACK = cvScalar(0,0,0);
const CvScalar C_RGB_WHITE = cvScalar(255,255,255);
const CvScalar C_GRAY_WHITE = cvScalar(255);
const CvScalar C_GRAY_BLACK= cvScalar(0);
const CvScalar C_RGB_RED = cvScalar(0,0,255);

void paintPixel(IplImage* in,int x, int y,CvScalar color) throw()
{   // comprueba que los puntos están dentro de la imagen
    if(in != NULL)
    {
        if(y>=0 && y<(in->height) && x>=0 && x<(in->width))
        {   // modifica el pixel a nivel de byte sobre el vector de la imagen.
            char *data = in->imageData;
            data[y*in->widthStep+x*in->nChannels]=color.val[0];
            data[y*in->widthStep+x*in->nChannels+1]=color.val[1];
            data[y*in->widthStep+x*in->nChannels+2]=color.val[2];
        }
    }
}

// TODO
bool comparePixel(IplImage* in,int x, int y,CvScalar color) throw()
{   // comprueba que los puntos están dentro de la imagen
    if(in != NULL)
    {
            char *data = in->imageData;
            return(data[y*in->widthStep+x*in->nChannels]==color.val[0]);
    }
    return false;
}

//this is a sample for foreground detection functions
int main(int argc, char** argv)
    {
    IplImage* tmp_frame = NULL;
    CvCapture* cap = NULL;

    cap = cvCreateCameraCapture(0);
    tmp_frame = cvQueryFrame(cap);

    if(!tmp_frame)
    {
        printf("bad video \n");
        exit(0);
    }

    cvNamedWindow("BG", 1);
    cvNamedWindow("FG", 1);
     cvNamedWindow("Original", 1);

    //create BG model
    CvBGStatModel* bg_model = cvCreateGaussianBGModel( tmp_frame );

    double t;
    IplImage* cpy;
    int x = 0;
    int y = 0;

    for( int fr = 1;tmp_frame; tmp_frame = cvQueryFrame(cap), fr++ )
    {
        t = (double) cvGetTickCount();
        // Background substraction
        cvUpdateBGStatModel( tmp_frame, bg_model );
        cpy = cvCloneImage( bg_model->foreground );

        for (x=(cpy->width-1);x>=0;x=x--)
            for (y=(cpy->height-1);y>= 0;y--)
                if(comparePixel(cpy,x,y,C_GRAY_BLACK))
                    paintPixel(tmp_frame,x,y,C_RGB_BLACK);

        cvShowImage("BG", bg_model->background);
        cvShowImage("FG", bg_model->foreground);
        cvShowImage("Original", tmp_frame);

        int k = cvWaitKey(15);
        if( k == 27 ) break;
        //printf("frame# %d \r", fr);
    }

    cvReleaseBGStatModel( &bg_model );
    cvReleaseCapture(&cap);

return 0;
}