Partage
  • Partager sur Facebook
  • Partager sur Twitter

OpenCV: cvSnakeImage

    23 juillet 2009 à 11:19:03

    Bonjour,

    j'aimerais extraire les points caractéristiques dans un visage pour l'identifier. Je n'ai pas trouvé de solutions pour localiser ces points dans une image à part l'utilisation de cvSnakeImage. J'ai parcouru la documentation de cette fonction que je ne maîtrise pas beaucoup et j'ai trouvé un exemple sur : http://www.lund.gl/ImageProcess/Customizing/Customizing2.html

    Je l'ai adapté sur une image contenant un oeil, mais je n'obtiens pas du tout le contour de l'oeil bien que je modifie le nombre de points de Snake, le nombre maximale d'itérations,etc. J'ai aussi essayé sur un visage complet, ça ne marche pas mieux. Pourriez-vous m'aider svp? Merci

    Voici le code adapté (j'utilise les cascades de Haar pour extraire les yeux êt dans la suite du traitement je m'intéresse à la région de l'oeil gauche:

    #include "stdafx.h"
    #include <windows.h>
    #include <iostream>
    #include <cv.h>
    #include <highgui.h>
    #include <io.h>
    #include <direct.h>
    #include <cstdlib>
    #include <fstream>

    using namespace std;

    static CvHaarClassifierCascade* cascade = 0;
    static CvMemStorage* storage = 0;
    CvRect * detect_and_draw( IplImage* image );
    const char* cascade_name = "C:/Program Files/OpenCV/data/haarcascades/haarcascade_eye.xml";

    CvRect* detect_and_draw( IplImage* img )
    {
    static CvScalar colors[] =
    {
    {{0,0,255}},
    {{0,128,255}},
    {{0,255,255}},
    {{0,255,0}},
    {{255,128,0}},
    {{255,255,0}},
    {{255,0,0}},
    {{255,0,255}}
    };

    /* creation tab rectangles contournant les regions d'interet */
    CvRect* rectangles= (CvRect*) malloc(10*sizeof(CvRect));

    double scale = 1.3;
    IplImage* gray = cvCreateImage( cvSize(img->width,img->height), 8, 1 );
    IplImage* small_img = cvCreateImage( cvSize( cvRound (img->width/scale),
    cvRound (img->height/scale)),8, 1 );
    int i;

    cvCvtColor( img, gray, CV_BGR2GRAY );
    cvResize( gray, small_img, CV_INTER_LINEAR );
    cvEqualizeHist( small_img, small_img );
    cvClearMemStorage( storage );

    if( cascade )
    {
    double t = (double)cvGetTickCount();
    CvSeq* faces = cvHaarDetectObjects( small_img, cascade, storage,
    1.1, 2, 0/*CV_HAAR_DO_CANNY_PRUNING*/,
    cvSize(30, 30) );
    t = (double)cvGetTickCount() - t;
    printf( "detection time = %gms\n", t/((double)cvGetTickFrequency()*1000.) );
    for( i = 0; i < (faces ? faces->total : 0); i++ )
    {
    CvRect* r = (CvRect*)cvGetSeqElem( faces, i );
    CvPoint center;
    int radius;
    center.x = cvRound((r->x + r->width*0.5)*scale);
    center.y = cvRound((r->y + r->height*0.5)*scale);
    radius = cvRound((r->width + r->height)*0.5*scale);

    //cvCircle( img, center, radius, colors[i%8], 3, 8, 0 );
    rectangles[i]= cvRect((r->x),(r->y),(r->width)*scale+10,(r->height)*scale+10);

    }
    }

    cvReleaseImage( &gray );
    cvReleaseImage( &small_img );
    return rectangles;
    }


    /* normalisation de la luminosité des images par étirement d'histogramme */
    void normaliser_luminosite(IplImage *img){
    if(img->nChannels!=1)
    return;

    double p_min = 255; /* valeur minimale souhaitée */
    double p_max = 0; /* valeur maximale souhaitée */

    CvScalar scalaire;

    //On parcourt toute l'image
    for(int x=0; x<img->width; x++)
    {
    for(int y=0; y<img->height; y++)
    {

    //On récupère le pixel de coordonnées (x,y)
    scalaire=cvGet2D(img, y, x);

    //Si le niveau de gris est inférieur à p_min, il devient p_min
    if(scalaire.val[0]<p_min)
    {
    p_min=scalaire.val[0];
    }

    //Si le niveau de gris est supérieur à p_max, il devient p_max
    if(scalaire.val[0]>p_max)
    {
    p_max=scalaire.val[0];
    }
    }
    }

    //p_min est maintenant le nvg minimum et p_max le nvg maximum

    //On parcourt l'image une seconde fois
    for(int x=0; x<img->width; x++)
    {
    for(int y=0; y<img->height; y++)
    {
    //On récupère le pixel (x,y)
    scalaire=cvGet2D(img, y, x);

    //Normalisation
    scalaire.val[0] = 255*(scalaire.val[0]-p_min);
    scalaire.val[0] = scalaire.val[0]/(p_max-p_min);

    //On remplace le pixel dans l'image
    cvSet2D(img, y, x, scalaire);
    }
    }

    }




    int main(){

    /* on charge la cascade de Haar */
    cascade = (CvHaarClassifierCascade*)cvLoad( cascade_name, 0, 0, 0 );
    storage = cvCreateMemStorage(0);
    const char* filename = "C:/Documents and Settings/seemap09/My Documents/My Pictures/test4.jpg";
    IplImage* image = cvLoadImage( filename, 1 );
    normaliser_luminosite(image);
    cvNamedWindow("result", CV_WINDOW_AUTOSIZE);
    CvRect* rectangles= detect_and_draw( image );
    cvShowImage( "result",image );
    normaliser_luminosite(image);

    /* extraction oeil gauche*/
    cvSetImageROI(image,rectangles[0]);
    IplImage* m_Ipl= cvCreateImage(cvGetSize(image),image->depth,1);
    //IplImage* gauche_seuillee= cvCreateImage(cvGetSize(image),image->depth,image->nChannels);
    IplImage* gauche_seuillee_grise= cvCreateImage(cvGetSize(image),image->depth,1);

    /* transformation en niveaux de gris */
    cvConvertImage(image,m_Ipl,0);


    //cvThreshold( (const CvArr*) gauche_grise,gauche_seuillee_grise,170, 255,CV_THRESH_BINARY);
    //cvThreshold( (const CvArr*) image,gauche_seuillee,120, 255,CV_THRESH_BINARY);

    cvNamedWindow("oeil_gauche", CV_WINDOW_AUTOSIZE);
    cvShowImage( "oeil_gauche",m_Ipl);

    IplImage *IplTmp1,*IplTmp2,*IplTmp3;
    IplTmp1 = cvCreateImage( cvGetSize(image), IPL_DEPTH_8U, 1 );
    IplTmp2 = cvCreateImage( cvGetSize(image) , IPL_DEPTH_8U, 1 );
    IplTmp3 = cvCreateImage(cvGetSize(image), IPL_DEPTH_8U, 1 );

    int ThressValue = 120;
    float alpha = 3;
    float beta = 5;
    float gamma = 2;
    CvSize win;
    CvTermCriteria criteria;
    int jumpPoint;
    CvPoint *WholePointArray;
    CvPoint *PointArray;
    const int NUMBER_OF_SNAKE_POINTS= 90;

    PointArray = (CvPoint *)malloc(NUMBER_OF_SNAKE_POINTS * sizeof(CvPoint));
    cvCopyImage( m_Ipl,IplTmp3); //IplTmp3 is the image to draw temp results to
    cvCopyImage( m_Ipl, IplTmp1);//(src,dst) copy to Working ipl image (IplTmp1 and IplTmp2 is working containers)
    // Make a average filtering
    cvSmooth(IplTmp1,IplTmp2,CV_BLUR,31,15);


    //Do a threshold
    cvThreshold(IplTmp2,IplTmp1,ThressValue,255,CV_THRESH_BINARY);


    // expand the thressholded image of ones -smoothing the edge.
    //And move start position of snake out since there are no ballon force
    cvDilate( IplTmp1, IplTmp2, NULL, 3);

    //Find the contours
    CvMemStorage *storage;
    CvSeq* contour = NULL;
    storage = cvCreateMemStorage (0);
    cvFindContours( IplTmp2,storage, &contour,sizeof(CvContour), CV_RETR_LIST, CV_CHAIN_APPROX_NONE );
    //Run through the found coutours
    while( contour != NULL )
    {
    if ( contour ->total >= NUMBER_OF_SNAKE_POINTS)
    {
    cvSmooth(m_Ipl,IplTmp2,CV_BLUR,7,3);
    WholePointArray = (CvPoint *)malloc(contour->total * sizeof(CvPoint));
    cvCvtSeqToArray(contour, WholePointArray, CV_WHOLE_SEQ); //Copy the contour to a array

    // Number of jumps between the desired points (downsample only!)
    jumpPoint = (int)(contour->total / NUMBER_OF_SNAKE_POINTS);
    for (int i=0; i < NUMBER_OF_SNAKE_POINTS; i++)
    {
    PointArray[i].x = WholePointArray[ (int)( i*jumpPoint)].x;
    PointArray[i].y = WholePointArray[ (int)( i*jumpPoint)].y;
    }

    // Now for the snake
    criteria.max_iter = 100; // Do max N iterations
    criteria.epsilon = 1; // If only N points is moved then terminate
    criteria.type = CV_TERMCRIT_EPS|CV_TERMCRIT_ITER;
    win.width = 21; // search for energi minimizing in this area around snake points
    win.height = 21; // Be sure that width and heigth is uneven

    // Iterate snake
    cvSnakeImage(IplTmp2, PointArray, NUMBER_OF_SNAKE_POINTS,&alpha,&beta,&gamma, CV_VALUE, win, criteria,1);
    // Draw snake on image

    int n = NUMBER_OF_SNAKE_POINTS;
    cvPolyLine( IplTmp3, &PointArray, &n, 1,1,cvScalar(255), 3,8 );

    free(WholePointArray);
    }
    //Get next contour
    contour = contour->h_next;
    }

    cvNamedWindow("Temp1",1);
    cvShowImage("Temp1",IplTmp1);
    cvNamedWindow("Temp2",1);
    cvShowImage("Temp2",IplTmp2);
    cvNamedWindow("Temp3",1);
    cvShowImage("Temp3",IplTmp3);
    cvWaitKey(0);

    /* reconsideration de l'image en entier */
    cvResetImageROI( image );

    //Clean up
    free (contour);
    free(PointArray);
    cvReleaseMemStorage(&storage);

    //Save result
    cvCopyImage( IplTmp3, m_Ipl);//(src,dst)

    // Clean up
    cvReleaseImage(&IplTmp1);
    cvReleaseImage(&IplTmp2);
    cvReleaseImage(&IplTmp3);
    return 0;
    }



    • Partager sur Facebook
    • Partager sur Twitter

    OpenCV: cvSnakeImage

    × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
    × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
    • Editeur
    • Markdown