2010-02-11 10 views
2

J'ai un problème avec mon programme écrit en Visual C++ en utilisant OpenCV: Je dois capturer des cadres de webcam et trouver tous les différents rectangle (peu importe la couleur). J'essaie de modifier les échantillons dans c, squares.c, mais ça ne marche pas aussi, parce que le programme attend une touche (différente de 'q') pour continuer.Détection d'objet dans openCV

Ceci est le code. Quelqu'un peut me dire où est le problème? Merci d'avance.

// 
// Object Detection of squares 
// Take images from webcam and find the square in them 
// 
// 
#include "stdafx.h" 
#include <stdio.h> 
#include <math.h> 
#include <string.h> 

int thresh = 50; 
IplImage* img = 0; 
IplImage* img0 = 0; 
CvMemStorage* storage = 0; 
//const char* wndname = "Square Detection Demo with Webcam"; 

// helper function: 
// finds a cosine of angle between vectors 
// from pt0->pt1 and from pt0->pt2 
double angle(CvPoint* pt1, CvPoint* pt2, CvPoint* pt0) 
{ 
    double dx1 = pt1->x - pt0->x; 
    double dy1 = pt1->y - pt0->y; 
    double dx2 = pt2->x - pt0->x; 
    double dy2 = pt2->y - pt0->y; 
    return (dx1*dx2 + dy1*dy2)/sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10); 
} 

// returns sequence of squares detected on the image. 
// the sequence is stored in the specified memory storage 
CvSeq* findSquares4(IplImage* img, CvMemStorage* storage) 
{ 
    CvSeq* contours; 
    int i, c, l, N = 11; 
    CvSize sz = cvSize(img->width & -2, img->height & -2); 
    IplImage* timg = cvCloneImage(img); // make a copy of input image 
    IplImage* gray = cvCreateImage(sz, 8, 1); 
    IplImage* pyr = cvCreateImage(cvSize(sz.width/2, sz.height/2), 8, 3); 
    IplImage* tgray; 
    CvSeq* result; 
    double s, t; 
    // create empty sequence that will contain points - 
    // 4 points per square (the square's vertices) 
    CvSeq* squares = cvCreateSeq(0, sizeof(CvSeq), sizeof(CvPoint), storage); 

    // select the maximum ROI in the image 
    // with the width and height divisible by 2 
    cvSetImageROI(timg, cvRect(0, 0, sz.width, sz.height)); 

    // down-scale and upscale the image to filter out the noise 
    cvPyrDown(timg, pyr, 7); 
    cvPyrUp(pyr, timg, 7); 
    tgray = cvCreateImage(sz, 8, 1); 

    // find squares in every color plane of the image 
    for(c = 0; c < 3; c++) 
    { 
     // extract the c-th color plane 
     cvSetImageCOI(timg, c+1); 
     cvCopy(timg, tgray, 0); 

     // try several threshold levels 
     for(l = 0; l < N; l++) 
     { 
      // hack: use Canny instead of zero threshold level. 
      // Canny helps to catch squares with gradient shading 
      if(l == 0) 
      { 
       // apply Canny. Take the upper threshold from slider 
       // and set the lower to 0 (which forces edges merging) 
       cvCanny(tgray, gray, 0, thresh, 5); 
       // dilate canny output to remove potential 
       // holes between edge segments 
       cvDilate(gray, gray, 0, 1); 
      } 
      else 
      { 
       // apply threshold if l!=0: 
       //  tgray(x,y) = gray(x,y) < (l+1)*255/N ? 255 : 0 
       cvThreshold(tgray, gray, (l+1)*255/N, 255, CV_THRESH_BINARY); 
      } 

      // find contours and store them all as a list 
      cvFindContours(gray, storage, &contours, sizeof(CvContour), 
       CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0)); 

      // test each contour 
      while(contours) 
      { 
       // approximate contour with accuracy proportional 
       // to the contour perimeter 
       result = cvApproxPoly(contours, sizeof(CvContour), storage, 
        CV_POLY_APPROX_DP, cvContourPerimeter(contours)*0.02, 0); 
       // square contours should have 4 vertices after approximation 
       // relatively large area (to filter out noisy contours) 
       // and be convex. 
       // Note: absolute value of an area is used because 
       // area may be positive or negative - in accordance with the 
       // contour orientation 
       if(result->total == 4 && 
        fabs(cvContourArea(result,CV_WHOLE_SEQ)) > 1000 && 
        cvCheckContourConvexity(result)) 
       { 
        s = 0; 
        printf("ciclo for annidato fino a 5\t\n"); 
        for(i = 0; i < 5; i++) 
        { 
         // find minimum angle between joint 
         // edges (maximum of cosine) 
         if(i >= 2) 
         { 
          t = fabs(angle(
          (CvPoint*)cvGetSeqElem(result, i), 
          (CvPoint*)cvGetSeqElem(result, i-2), 
          (CvPoint*)cvGetSeqElem(result, i-1))); 
          s = s > t ? s : t; 
         } 
        } 

        // if cosines of all angles are small 
        // (all angles are ~90 degree) then write quandrange 
        // vertices to resultant sequence 
        if(s < 0.3) 
         for(i = 0; i < 4; i++) 
          cvSeqPush(squares, 
           (CvPoint*)cvGetSeqElem(result, i)); 
       } 

       // take the next contour 
       contours = contours->h_next; 
      } 
     } 
    } 

    // release all the temporary images 
    cvReleaseImage(&gray); 
    cvReleaseImage(&pyr); 
    cvReleaseImage(&tgray); 
    cvReleaseImage(&timg); 

    return squares; 
} 


// the function draws all the squares in the image 
void drawSquares(IplImage* img, CvSeq* squares) 
{ 
    CvSeqReader reader; 
    IplImage* cpy = cvCloneImage(img); 
    int i; 

    // initialize reader of the sequence 
    cvStartReadSeq(squares, &reader, 0); 

    // read 4 sequence elements at a time (all vertices of a square) 
    for(i = 0; i < squares->total; i += 4) 
    { 
     CvPoint pt[4], *rect = pt; 
     int count = 4; 

     // read 4 vertices 
     CV_READ_SEQ_ELEM(pt[0], reader); 
     CV_READ_SEQ_ELEM(pt[1], reader); 
     CV_READ_SEQ_ELEM(pt[2], reader); 
     CV_READ_SEQ_ELEM(pt[3], reader); 

     // draw the square as a closed polyline 
     cvPolyLine(cpy, &rect, &count, 1, 1, CV_RGB(0,255,0), 3, CV_AA, 0); 
    } 
cvSaveImage("squares.jpg",cpy); 

    //show the resultant image 
    //cvShowImage(wndname, cpy); 
    cvReleaseImage(&cpy); 
//return cpy; 
} 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
int key = 0; 
IplImage* frame =0; 
IplImage* squares=0; 
    // create memory storage that will contain all the dynamic data 
    storage = cvCreateMemStorage(0); 

CvCapture *camera = cvCreateCameraCapture(CV_CAP_ANY); /* Usa USB camera */ 

frame = cvQueryFrame(camera); 
frame = cvQueryFrame(camera); 
frame = cvQueryFrame(camera); 

while(key!='q'){ 

    frame = cvQueryFrame(camera); 
    frame = cvQueryFrame(camera); 

    if(frame!=NULL){ 
    printf("Got frame\t\n"); 

    cvSaveImage("frame.jpg", frame); 

    /*img0*/ img = cvLoadImage("frame.jpg"); 

    //img = cvCloneImage(img0); 

    cvNamedWindow("img0", CV_WINDOW_AUTOSIZE); 

    cvShowImage("img0",/*img0*/img); 

    // find and draw the squares 

    drawSquares(img, findSquares4(img, storage)); 

    squares = cvLoadImage("squares.jpg"); 

    // create window and a trackbar (slider) 
         //with parent "image" and set callback 
    //(the slider regulates upper threshold, 
         //passed to Canny edge detector) 
    cvNamedWindow("main", CV_WINDOW_AUTOSIZE); 
    cvShowImage("main", squares); 

    /* wait for key. 
    Also the function cvWaitKey takes care of event processing */ 
    key = cvWaitKey(0); 

    } 
} 

     // release both images 
     cvReleaseImage(&img); 
     cvReleaseImage(&img0); 
    cvReleaseCapture(&camera); 
    cvDestroyWindow("main"); 
    cvDestroyWindow("img0"); 
     // clear memory storage - reset free space position 
     cvClearMemStorage(storage); 

    return 0; 
    } 
+1

Le titre de la question suggère que vous avez un problème OpenCV, mais alors vous dites quelque chose au sujet de la touche 'q'? S'il vous plaît isoler le problème précis, en réduisant votre code au plus petit échantillon qui montre encore le problème. Ensuite, clarifiez ce que vous voyez et ce que vous attendiez. – MSalters

+0

Vous pouvez vérifier ce lien sur stackoverflow. http://stackoverflow.com/questions/5217519/opencv-cvwaitkey – tan

Répondre

0

Si votre problème est que la fenêtre dissappers sans attendre coup à partir du clavier, vous pouvez ajouter un cvWaitKey (0) à la fin du code.

De plus, un getch() à la fin aiderait. assurez-vous d'inclure dans les en-têtes.

+0

Désolé, j'ai mal tapé. J'explique mieux le problème: le programme fonctionne, mais il s'arrête après le chargement de l'image, qui a été sauvegardé en premier dans la fonction findSquares4() et il ne continue pas car il attend une clé. Je ne trouve pas l'erreur. Quelqu'un peut-il me dire pourquoi il attend une clé ?? Merci d'avance. –

+0

dans la fonction drawSquares() l'image squares.jpg est enregistrée. –

+0

Merci pour votre réponse, mais je trouve l'erreur. C'était la fonction cvLoadImage(), parce que le programme essaie de charger une image qui n'existe pas quand je lance le programme pour la première fois. Donc, travailler avec le cadre sans enregistrer et charger, le programme fonctionne .. ^^ –

3

Je crois que votre problème est ici:

/* wait for key. 
    Also the function cvWaitKey takes care of event processing */ 
    key = cvWaitKey(0); 

Essayez de changer 0 à 10.

Je vois dans votre code d'autres problèmes. Par exemple, vous créez des fenêtres dans la boucle while, ce qui n'est pas bon. Essayez de déplacer les appels de fonction cvNamedWindow() en dehors de votre boucle while. En outre, je ne suis pas sûr pourquoi vous interrogez la caméra pour les cadres et ne les traitez pas?

+0

Merci pour votre réponse, mais je trouve l'erreur. C'était la fonction cvLoadImage(), parce que le programme essaie de charger une image qui n'existe pas quand je cours pour la première fois le programme. Donc travailler avec frame sans enregistrer et charger, le programme fonctionne .. ^^ –