Thông báo

Collapse
No announcement yet.

Nhận dạng các hình cơ bản (Vuông, tròn và tam giác) với Opencv trên C++

Collapse
X
 
  • Lọc
  • Giờ
  • Show
Clear All
new posts

  • Nhận dạng các hình cơ bản (Vuông, tròn và tam giác) với Opencv trên C++

    các anh có thể cho e hỏi về vấn đề nhận dạng các hình cơ bản đuọc không ạ,
    e có làm đề tài về vấn đề này, nhưng mà không hiểu sao mà làm mãi vẫn không ra được, lúc thì nhiễu, lúc thì không hiện được, các a xem giúp e.
    e có gởi kèm file để tiện theo dõi
    Last edited by hoang bui; 11-12-2010, 01:38.

  • #2
    híc, tải file lên hoài mà không được, thôi e post lên vậy:

    #include "cv.h"
    #include "highgui.h"
    #include "math.h"
    #include "cxcore.h"
    #include <iostream>
    #include <stdio.h>
    #include <math.h>
    #include <string.h>
    #include <conio.h>
    #include <sstream>

    using namespace std;



    // 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 )
    {
    double s = 0, t = 0;
    CvSeq* contours = NULL;
    CvSeq* result = NULL;

    // create empty sequence that will contain points -
    // 4 points per square (the square's vertices)
    CvSeq* squares = cvCreateSeq( 0, sizeof( CvSeq), sizeof( CvPoint), storage );

    // find contours and store them all as a list
    cvFindContours( img, 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 && fabs( cvContourArea( result, CV_WHOLE_SEQ)) <( img->height * img->width/2 ) && cvCheckContourConvexity( result) )
    {
    s = 0;
    for( int 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.5 )
    for( int i = 0; i < 4; i++ )cvSeqPush( squares, ( CvPoint*)cvGetSeqElem( result, i ));
    }


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



    void drawSquares(IplImage *img, CvSeq* squares )
    {
    int i,j = 0;
    CvSeqReader reader;
    cvStartReadSeq( squares, &reader, 0 );

    // read 4 sequence elements at a time (all vertices of a square)
    for( i = 0; i < squares->total; i += 4 )
    {
    j++;
    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
    cvLine( img, pt[0], pt[1], CV_RGB(200,0,0),5, 8, 0); // canh 1, so 5 là do day net ve~
    cvLine( img, pt[1], pt[2], CV_RGB(200,0,0),5, 8, 0); // canh 2
    cvLine( img, pt[2], pt[3], CV_RGB(200,0,0),5, 8, 0); // canh 3
    cvLine( img, pt[3], pt[0], CV_RGB(200,0,0),5, 8, 0); // canh 4


    double angle = abs(pt[1].y-pt[2].y)/sqrt((pt[1].x-pt[2].x)*(pt[1].x-pt[2].x)+(pt[1].y-pt[2].y)*(pt[1].y-pt[2].y)+0.00001);
    char st[255];
    sprintf(st, "%2f", angle);

    for (int i = 0; i < int( angle*10); i++) cvRectangle( img, cvPoint((j-1)*30 , i*12+10), cvPoint((j-1)*30+27 , i*12), CV_RGB(255 * angle, 255*(1-angle), 0), -1, 8, 0 ); // thang chay



    // draw the square as a closed polyline
    cvPolyLine( img, &rect, &count, 1, 1, CV_RGB(200,0,0), 1, CV_AA, 0 );
    }
    }



    // returns sequence of triangles detected on the image.
    // the sequence is stored in the specified memory storage
    CvSeq* findTriangles4( IplImage* img, CvMemStorage* storage )
    {
    double s = 0, t = 0;
    CvSeq* contours = NULL;
    CvSeq* result = NULL;

    // create empty sequence that will contain points -
    // 3 points per triangles (the triangles'vertices)
    CvSeq* Triangles = cvCreateSeq( 0, sizeof( CvSeq), sizeof( CvPoint), storage );


    // find contours and store them all as a list
    cvFindContours( img, 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 );

    // triangles 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 == 3 && fabs( cvContourArea( result, CV_WHOLE_SEQ)) > 1000 && fabs( cvContourArea( result, CV_WHOLE_SEQ)) <( img->height * img->width/2 ) && cvCheckContourConvexity( result) )
    {
    s = 0;
    for( int i = 0; i < 4; 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.5 )for( int i = 0; i < 3; i++ )cvSeqPush( Triangles, ( CvPoint*)cvGetSeqElem( result, i ));
    }

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

    /*==========================================*/


    // ve tam giac
    void drawTriangles(IplImage *img, CvSeq* Triangles )
    {
    int i,j = 0;
    CvSeqReader reader;


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

    // read 3 sequence elements at a time (all vertices of a triangles)
    for( i = 0; i < Triangles->total; i += 3 )
    {
    j++;
    CvPoint pt[3], *Trgles = pt;
    int count = 3;


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


    // draw the square as a closed polyline
    cvLine( img, pt[0], pt[1], CV_RGB(200,0,0), 5, 8, 0); // canh 1, so 5 là do day net ve~
    cvLine( img, pt[1], pt[2], CV_RGB(200,0,0), 5, 8, 0); // canh 2
    cvLine( img, pt[2], pt[0], CV_RGB(200,0,0), 5, 8, 0); // canh 3


    double angle = abs(pt[1].y-pt[2].y)/sqrt((pt[1].x-pt[2].x)*(pt[1].x-pt[2].x)+(pt[1].y-pt[2].y)*(pt[1].y-pt[2].y)+0.00001);
    char st[255];
    sprintf(st, "%2f", angle);

    cvPolyLine( img, &Trgles, &count, 1, 1, CV_RGB(0,200,0), 1, CV_AA, 0 );// duong` net' goc'
    }
    }




    int main
    {


    int c;
    int px[10], py[10];
    int edge_thresh = 1;
    CvCapture* capture=cvCaptureFromCAM(0);
    if(!cvQueryFrame(capture)){cout<<"Video capture failed, please check the camera."<<endl;}else{cout<<"Video camera capture status: Ok"<<endl;};
    CvSize sz = cvGetSize(cvQueryFrame(capture));
    IplImage *src = 0;
    IplImage *gray = cvCreateImage( sz, 8, 1 );
    IplImage *edge = cvCreateImage( sz, 8, 1 );
    CvMemStorage* cstorage = cvCreateMemStorage(0);
    IplImage* tgray = cvCreateImage( sz, 8, 1 );

    // create memory storage that will contain all the dynamic data
    CvMemStorage* storage = cvCreateMemStorage(0);
    CvSeq* contours = NULL;

    // create memory storage that will contain all the dynamic data
    CvMemStorage* mainStorage = cvCreateMemStorage(0);

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

    /*=========================*/

    //loop start here

    while(1)
    {
    src=cvQueryFrame(capture);
    cvCvtColor(src,gray,CV_BGR2GRAY); //convert video image color
    gray->origin=1; //set the converted image's origin
    cvThreshold(gray,gray,100,255,CV_THRESH_BINARY);//color threshold
    // cvSmooth( gray, gray, CV_GAUSSIAN, 11, 11 ); //smooth the image to reduce unneccesary results
    cvCanny(gray, edge, (float)edge_thresh, (float)edge_thresh*3, 5); //get edges

    IplImage* img = NULL;
    IplImage* out = NULL;
    src = cvQueryFrame( capture);
    img = cvCloneImage( src);
    out = cvCloneImage( src);
    cvSetImageCOI( img, 2 );
    cvCopy( img, tgray, 0 );
    cvThreshold( tgray, gray, 100, 255, CV_THRESH_BINARY );
    cvFindContours( gray, storage, &contours, sizeof(CvContour), CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0) );

    // triangle

    if (findTriangles4)
    {

    drawTriangles(out,findTriangles4(gray,mainStorage) );
    cvReleaseImage( &img);
    cvShowImage( "src", out);
    cvReleaseImage( &out);
    c = cvWaitKey(10);

    }





    // hinh vuong

    // find and draw the squares
    if (findSquares4)
    {
    // cvFindContours( gray, storage, &contours, sizeof(CvContour), CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0) );

    drawSquares(out,findSquares4(gray,mainStorage));

    // release images
    cvReleaseImage( &img);
    cvShowImage( "src", out);
    cvReleaseImage( &out);


    // wait for key
    // Also the function cvWaitKey takes care of event processing
    c = cvWaitKey(10);
    }



    // hinh tron

    if (cvHoughCircles( gray, cstorage, CV_HOUGH_GRADIENT, 1, gray->height/100, 6, 100 ))
    {

    cvSmooth( gray, gray, CV_GAUSSIAN, 11, 11 ); //smooth the image to reduce unneccesary results

    CvSeq* circles = cvHoughCircles( gray, cstorage, CV_HOUGH_GRADIENT, 1, gray->height/100, 6, 100 );//1,100,5,55 get circles, so 10 là do chinh xac cua viec xac dinh, cang lon cang chinh xac
    //start drawing all the circles
    int i;
    for( i = 0; circles->total>=1?i<1:i < circles->total; i++ )
    { //just make a filter to limit only <=1 ciecles to draw
    float* p = (float*)cvGetSeqElem( circles, i );
    cvCircle( src, cvPoint(cvRound(p[0]),cvRound(p[1])), 3, CV_RGB(255,0,0), -1, 8, 0 );
    cvCircle( src, cvPoint(cvRound(p[0]),cvRound(p[1])), cvRound(p[2]), CV_RGB(200,0,0), 5, 8, 0 );// so 5 la do day net ve~ cua duong` tron`
    px[i]=cvRound(p[0]);
    py[i]=cvRound(p[1]);
    }


    cvShowImage("src",src);
    c=cvWaitKey(10);//ready to exit loop
    if(c==27)break;
    }
    }



    //release video capture
    cvReleaseCapture( &capture);
    //release all windows
    cvDestroyAllWindows();


    }

    Comment


    • #3
      các anh chị xem jup' jum` e.
      e xin cảm ơn trước lun ^^

      Comment


      • #4
        Nguyên văn bởi hoang bui Xem bài viết
        các anh chị xem jup' jum` e.
        e xin cảm ơn trước lun ^^
        bạn có thể chụp ảnh màn hình cái lỗi đó or post cụ thể nó là lỗi j được ko?
        Như thế này giúp làm sao được!
        Bể học vô biên

        Comment


        • #5
          Nguyên văn bởi hoang bui Xem bài viết
          các anh có thể cho e hỏi về vấn đề nhận dạng các hình cơ bản đuọc không ạ,
          e có làm đề tài về vấn đề này, nhưng mà không hiểu sao mà làm mãi vẫn không ra được, lúc thì nhiễu, lúc thì không hiện được, các a xem giúp e.
          e có gởi kèm file để tiện theo dõi

          nhiễu thì bạn xử lý lại nó tốt nhất là bạn thêm vào erosion và dilation
          ko hiện đc thì bạn release image ở vòng lặp như vậy thì hiện sao đc nữa
          để cái release ở hàm main thôi
          Last edited by LCD_4BIT; 11-12-2010, 12:29.
          Bể học vô biên

          Comment


          • #6
            Nguyên văn bởi LCD_4BIT Xem bài viết
            bạn có thể chụp ảnh màn hình cái lỗi đó or post cụ thể nó là lỗi j được ko?
            Như thế này giúp làm sao được!
            lỗi của e là khi để chương trình nhận dạng cả 3 hình, nếu để code nhận hình vuông ở trên code nhận hình tam giác, thì chỉ nhận được hình vuông và hình tròn, còn tam giác thì không nhận được,
            còn nhiễu thì là do nhiều khi nhận hình vuông, thì hình tròn tự nhiên lại hiện ra, nên e cũng không hiểu

            Comment


            • #7
              Nguyên văn bởi LCD_4BIT Xem bài viết
              nhiễu thì bạn xử lý lại nó tốt nhất là bạn thêm vào erosion và dilation
              ko hiện đc thì bạn release image ở vòng lặp như vậy thì hiện sao đc nữa
              để cái release ở hàm main thôi
              cho e hỏi là nếu dùng 2 ham này thì mình dùng như thế nào ạ.

              Comment


              • #8
                Nguyên văn bởi hoang bui Xem bài viết
                cho e hỏi là nếu dùng 2 ham này thì mình dùng như thế nào ạ.
                2 hàm này mục đích là lọc hình thái học. nghĩa là nó giúp bạn loại bỏ những nhiễu nhỏ li ti như các dấu chấm trên ảnh ()
                như ở đây bạn sẽ thấy các chữ và số không cần thiết sẽ bị loại bỏ hình dạng của vật sẽ ro ràng hơn
                chi tiết bạn có thể tham khảo tại: http://dasl.mem.drexel.edu/~noahKuntz/openCVTut4.html



                goodluck !
                Bể học vô biên

                Comment


                • #9
                  a có thể cho e hỏi về bộ nhớ chương trình trong Opencv được không ạ, khi e chạy chương trình, sau một lúc thì bộ nhớ chương trình bị đầy, e có dùng lệnh cvClearMemStorage( storage );, sau khi dùng mà không được, e có chuyển sang dùng cvReleaseMemStorage( &storage );
                  nhưng mà không hiểu sao vẫn không được.
                  các a có thể cho e hỏi là nên dùng lệnh xóa bộ nhớ nào? và nên dùng tại vị trí nào không ạ??
                  e xin cảm ơn!!!

                  Comment


                  • #10
                    Nguyên văn bởi hoang bui Xem bài viết
                    a có thể cho e hỏi về bộ nhớ chương trình trong Opencv được không ạ, khi e chạy chương trình, sau một lúc thì bộ nhớ chương trình bị đầy, e có dùng lệnh cvClearMemStorage( storage );, sau khi dùng mà không được, e có chuyển sang dùng cvReleaseMemStorage( &storage );
                    nhưng mà không hiểu sao vẫn không được.
                    các a có thể cho e hỏi là nên dùng lệnh xóa bộ nhớ nào? và nên dùng tại vị trí nào không ạ??
                    e xin cảm ơn!!!
                    @hoangbui
                    Mình nghĩ cái này có thể giúp được bạn

                    http://tech.groups.yahoo.com/group/OpenCV/message/65793

                    Thân!
                    Bể học vô biên

                    Comment


                    • #11
                      ah`, còn về phần chương trình
                      e có viết nhận code (hiện tại đã chuyển sang nhận dạng tam giác, vuông, ngũ giác), e có định nghĩa các hàm nhận dạng từ trước và cũng có định nghĩa hàm vẽ từ trước, nhưng mà đến khi vào chương trình chính thì lại bị lặp rất nhiều lần,
                      giả sử e cho
                      truyền đi "T" khi nhận được tam giác
                      truyền đi "S" khi nhận được hình vuông
                      truyền đi "P" khi nhận được ngũ giác
                      khi vào chương trình chính, thì thấy truyền đi liên tục TSPTSPTSPTSP...
                      chứ ko dừng tại một vị trí.
                      không biết là làm sao để có thế chỉ truyền một kí tự khi nhận đc hình thôi ko^^, chà, mấy cái này làm e đau đầu mấy bữa nay.híc.
                      e xin cảm ơn!!!

                      Comment


                      • #12
                        Nguyên văn bởi hoang bui Xem bài viết
                        ah`, còn về phần chương trình
                        e có viết nhận code (hiện tại đã chuyển sang nhận dạng tam giác, vuông, ngũ giác), e có định nghĩa các hàm nhận dạng từ trước và cũng có định nghĩa hàm vẽ từ trước, nhưng mà đến khi vào chương trình chính thì lại bị lặp rất nhiều lần,
                        giả sử e cho
                        truyền đi "T" khi nhận được tam giác
                        truyền đi "S" khi nhận được hình vuông
                        truyền đi "P" khi nhận được ngũ giác
                        khi vào chương trình chính, thì thấy truyền đi liên tục TSPTSPTSPTSP...
                        chứ ko dừng tại một vị trí.
                        không biết là làm sao để có thế chỉ truyền một kí tự khi nhận đc hình thôi ko^^, chà, mấy cái này làm e đau đầu mấy bữa nay.híc.
                        e xin cảm ơn!!!
                        Cái này thì không thuộc vào xử lý ảnh rồi
                        Đơn giản là bạn dùng một hàm so sánh các giá trị liên tiếp nếu 2 giá trị liên tiếp nhận được là bằng nhau thì bạn không truyền nếu khác nhau thì truyền.


                        Thân!
                        Bể học vô biên

                        Comment


                        • #13
                          cảm ơn a, e làm được rồi ạ. các a chị trong diễn đàn tốt và nhiệt tình quá ạ. em xin chân thành cảm ơn!!!

                          Comment


                          • #14
                            Nguyên văn bởi hoang bui Xem bài viết
                            cảm ơn a, e làm được rồi ạ. các a chị trong diễn đàn tốt và nhiệt tình quá ạ. em xin chân thành cảm ơn!!!
                            Lúc nào có kết quả show lên cho mọi người xem nhé
                            Lên diễn đàn là để anh em học tập nhau mà

                            Thanks bạn!
                            Bể học vô biên

                            Comment

                            Về tác giả

                            Collapse

                            hoang bui Tìm hiểu thêm về hoang bui

                            Bài viết mới nhất

                            Collapse

                            Đang tải...
                            X