如何计算手指的数量? (openCV+轮廓检测)

发布于 2024-11-03 00:55:42 字数 5598 浏览 3 评论 0原文

我开始使用 findContour 查找手部轮廓,但是当我想使用 convHull2convextyDefect 计算手指时,我不知道该怎么做。

请你帮助我好吗?这是我的代码:

if( cascade1 )
{
static CvMemStorage* storage4 = 0;
static CvMemStorage* storage5 = 0;
static CvMemStorage* storage6 = 0;
static CvMemStorage* storage7 = 0;


CvSeq* contours;
CvSeq* hand_contour = NULL;

// There can be more than one hand in an image. So create a growable sequence of hands.
// Detect the objects and store them in the sequence
CvSeq* handsO = cvHaarDetectObjects( img, cascade1, storage1,1.1, 2, CV_HAAR_DO_CANNY_PRUNING,cvSize(40, 40) );

storage4 = cvCreateMemStorage(0);
storage5 = cvCreateMemStorage(0);
storage6 = cvCreateMemStorage(0);
storage7 = cvCreateMemStorage(0);

cvClearMemStorage( storage4 );
cvClearMemStorage( storage5 );
cvClearMemStorage( storage6 );
cvClearMemStorage( storage7 );


// Loop the number of hands found.
for( i = 0; i < (handsO ? handsO->total : 0); i++ )
{
    // Create a new rectangle for drawing the hand
    CvRect* r = (CvRect*)cvGetSeqElem( handsO, i );

    // Find the dimensions of the hand,and scale it if necessary
    pt1.x = r->x*scale;
    pt2.x = (r->x+r->width)*scale;
    pt1.y = r->y*scale;
    pt2.y = (r->y+r->height)*scale;

    /////////////////////  start hand contour detection////////////////////////

    // after finding the hand set it as the area of intrest of the image so all of the functions after that will apply only to that area
    cvSetImageROI(Rhand, cvRect(r->x*scale, r->y*scale, r->width*scale, r->height*scale));
    /*
    / prepare the image to the findContour function
    / 1- convert it to gray
    / 2- threshhold it
    / 3- find the edge
    */
    cvShowImage( "gray hand", Rhand);
    cvThreshold( Rhand, Rhand, 1, 255, CV_THRESH_BINARY );
    cvShowImage( "Threshold hand", Rhand);
    cvCanny(Rhand, Rhand, 1, 3, 5);
    cvShowImage( "Edge hand", Rhand);

    /*
    // cloasing after threshold to test if it will be a beter result 
    IplConvKernel* kernel = 0;
    kernel = cvCreateStructuringElementEx(5,5,0,0, CV_SHAPE_RECT);
    cvDilate(Rhand,Rhand,kernel,1);
    cvErode(Rhand,Rhand,kernel,1);
    */


    // find all contour  in the image
    cvFindContours(Rhand,storage4,&contours,sizeof(CvContour),CV_RETR_LIST,CV_CHAIN_APPROX_SIMPLE,cvPoint(0,0));

//  printf("\ncontour num%d",contours->total);
    // find the beggest contour and make it as the hand by comaring the area of each contour
    double area=0,biggestArea=0;
    while(contours)
    {
        area = fabs( cvContourArea( contours, CV_WHOLE_SEQ ) );
        //printf("\n\\\\\\\\\\\\\\\\\\\\\%f",area);

        if ( area > biggestArea) 
        {
        biggestArea = area; 
        hand_contour = contours;
        //printf("\n\\\\\\\\\\\\\\\\\\\\biggest\\\\\\\\\\\\\\%d",hand_contour->total);
        };

        contours  =  contours->h_next;
    }

    cvWaitKey(0);       

    if(hand_contour)
    {

        hand_contour = cvApproxPoly( hand_contour, sizeof(CvContour), storage7, CV_POLY_APPROX_DP, 3, 1 );
        CvRect rect = cvBoundingRect(hand_contour, 1 );
        CvBox2D box = cvMinAreaRect2( hand_contour, storage6 );
        //draw the rectangle arround the contour
        cvRectangle( img, cvPoint(rect.x, rect.y + rect.height), cvPoint(rect.x + rect.width, rect.y), CV_RGB(255, 255, 0), 1, 8, 0 );

        // preparing to detect the finger and compute/ draw them
        CvSeq* hull = cvConvexHull2( hand_contour, 0, CV_CLOCKWISE, 0 );
        int numOfHull =hull->total;
        CvPoint*  hullPoints;
        hullPoints = ( CvPoint *)malloc((hull->total)*sizeof(CvSeq));
        cvCvtSeqToArray(hull,hullPoints);           

        CvSeq* defect = cvConvexityDefects( hand_contour, hull, storage5 );
        int numOfdefect =defect->total;
        CvConvexityDefect* defectArray;
        defectArray = (CvConvexityDefect*)malloc(sizeof(CvConvexityDefect)*numofdefect);  
        cvCvtSeqToArray(defect,defectArray); 

        /*int h1,h2;
        for(i=0; i<numofHull-1; i++)  
        { 
            h1=hull[i];
            h2=hull[i+1];
            cvLine(img, defectArray[h1],defectArray[h2],CV_RGB(255,255,255),1, CV_AA, 0 );  
        }
        int h3=hull[numofHull-1],h4=hull[0];
        cvLine(img, defectArray[h3],defectArray[h4],CV_RGB(255,255,255),1, CV_AA, 0 );  
       // Free memory.            
       free(defectArray);  
       free(hull);  */

       int m=10;
        //cvPolyLine(img,&hullPoints,&m,CV_RGB( 0, 0, 100),1,8,0);
        //cvPolyLine( img, &hullPoints, &m, 2, 0, CV_RGB(0,0,100),10, CV_AA, 0);

        cvCircle( img, cvPoint(pt1.x, pt1.y), 3, CV_RGB(255, 128, 0), 3, 8, 0 );    
        cvCircle( img, cvPoint(box.center.x, box.center.y), 3, CV_RGB(75, 243, 243), 1, 8, 0 );
        cvEllipse( img, cvPoint(pt1.x, pt1.y), cvSize(box.size.height/2, box.size.width/2), box.angle, 0, 360, CV_RGB(220, 0, 120), 2, 8, 0 );
        cvDrawContours( Rhand, hand_contour,  CV_RGB( 0, 200, 100), CV_RGB( 100, 0, 0), 1, 1, 8, cvPoint(pt1.x,pt1.y));
        cvDrawContours( img, hand_contour,  CV_RGB( 0, 200, 100), CV_RGB( 100, 0, 0), 1, 1, 8, cvPoint(pt1.x,pt1.y));
        cvShowImage( "Rhand after draw contour", Rhand);
        cvShowImage( "img After draw contour", img);

        cvResetImageROI(Rhand);
        ///////////////////// End hand contour detection////////////////////////
}
// Draw the rectangle in the input image
 cvRectangle( img, pt1, pt2, CV_RGB(0,255,0), 3, 8, 0 );
}
cvClearSeq(handsO);
}

I start to find hand contour with findContour but when I want to compute the finger with convHull2 and convextyDefect I do not know what to do.

Could you please help me? Here is my code:

if( cascade1 )
{
static CvMemStorage* storage4 = 0;
static CvMemStorage* storage5 = 0;
static CvMemStorage* storage6 = 0;
static CvMemStorage* storage7 = 0;


CvSeq* contours;
CvSeq* hand_contour = NULL;

// There can be more than one hand in an image. So create a growable sequence of hands.
// Detect the objects and store them in the sequence
CvSeq* handsO = cvHaarDetectObjects( img, cascade1, storage1,1.1, 2, CV_HAAR_DO_CANNY_PRUNING,cvSize(40, 40) );

storage4 = cvCreateMemStorage(0);
storage5 = cvCreateMemStorage(0);
storage6 = cvCreateMemStorage(0);
storage7 = cvCreateMemStorage(0);

cvClearMemStorage( storage4 );
cvClearMemStorage( storage5 );
cvClearMemStorage( storage6 );
cvClearMemStorage( storage7 );


// Loop the number of hands found.
for( i = 0; i < (handsO ? handsO->total : 0); i++ )
{
    // Create a new rectangle for drawing the hand
    CvRect* r = (CvRect*)cvGetSeqElem( handsO, i );

    // Find the dimensions of the hand,and scale it if necessary
    pt1.x = r->x*scale;
    pt2.x = (r->x+r->width)*scale;
    pt1.y = r->y*scale;
    pt2.y = (r->y+r->height)*scale;

    /////////////////////  start hand contour detection////////////////////////

    // after finding the hand set it as the area of intrest of the image so all of the functions after that will apply only to that area
    cvSetImageROI(Rhand, cvRect(r->x*scale, r->y*scale, r->width*scale, r->height*scale));
    /*
    / prepare the image to the findContour function
    / 1- convert it to gray
    / 2- threshhold it
    / 3- find the edge
    */
    cvShowImage( "gray hand", Rhand);
    cvThreshold( Rhand, Rhand, 1, 255, CV_THRESH_BINARY );
    cvShowImage( "Threshold hand", Rhand);
    cvCanny(Rhand, Rhand, 1, 3, 5);
    cvShowImage( "Edge hand", Rhand);

    /*
    // cloasing after threshold to test if it will be a beter result 
    IplConvKernel* kernel = 0;
    kernel = cvCreateStructuringElementEx(5,5,0,0, CV_SHAPE_RECT);
    cvDilate(Rhand,Rhand,kernel,1);
    cvErode(Rhand,Rhand,kernel,1);
    */


    // find all contour  in the image
    cvFindContours(Rhand,storage4,&contours,sizeof(CvContour),CV_RETR_LIST,CV_CHAIN_APPROX_SIMPLE,cvPoint(0,0));

//  printf("\ncontour num%d",contours->total);
    // find the beggest contour and make it as the hand by comaring the area of each contour
    double area=0,biggestArea=0;
    while(contours)
    {
        area = fabs( cvContourArea( contours, CV_WHOLE_SEQ ) );
        //printf("\n\\\\\\\\\\\\\\\\\\\\\%f",area);

        if ( area > biggestArea) 
        {
        biggestArea = area; 
        hand_contour = contours;
        //printf("\n\\\\\\\\\\\\\\\\\\\\biggest\\\\\\\\\\\\\\%d",hand_contour->total);
        };

        contours  =  contours->h_next;
    }

    cvWaitKey(0);       

    if(hand_contour)
    {

        hand_contour = cvApproxPoly( hand_contour, sizeof(CvContour), storage7, CV_POLY_APPROX_DP, 3, 1 );
        CvRect rect = cvBoundingRect(hand_contour, 1 );
        CvBox2D box = cvMinAreaRect2( hand_contour, storage6 );
        //draw the rectangle arround the contour
        cvRectangle( img, cvPoint(rect.x, rect.y + rect.height), cvPoint(rect.x + rect.width, rect.y), CV_RGB(255, 255, 0), 1, 8, 0 );

        // preparing to detect the finger and compute/ draw them
        CvSeq* hull = cvConvexHull2( hand_contour, 0, CV_CLOCKWISE, 0 );
        int numOfHull =hull->total;
        CvPoint*  hullPoints;
        hullPoints = ( CvPoint *)malloc((hull->total)*sizeof(CvSeq));
        cvCvtSeqToArray(hull,hullPoints);           

        CvSeq* defect = cvConvexityDefects( hand_contour, hull, storage5 );
        int numOfdefect =defect->total;
        CvConvexityDefect* defectArray;
        defectArray = (CvConvexityDefect*)malloc(sizeof(CvConvexityDefect)*numofdefect);  
        cvCvtSeqToArray(defect,defectArray); 

        /*int h1,h2;
        for(i=0; i<numofHull-1; i++)  
        { 
            h1=hull[i];
            h2=hull[i+1];
            cvLine(img, defectArray[h1],defectArray[h2],CV_RGB(255,255,255),1, CV_AA, 0 );  
        }
        int h3=hull[numofHull-1],h4=hull[0];
        cvLine(img, defectArray[h3],defectArray[h4],CV_RGB(255,255,255),1, CV_AA, 0 );  
       // Free memory.            
       free(defectArray);  
       free(hull);  */

       int m=10;
        //cvPolyLine(img,&hullPoints,&m,CV_RGB( 0, 0, 100),1,8,0);
        //cvPolyLine( img, &hullPoints, &m, 2, 0, CV_RGB(0,0,100),10, CV_AA, 0);

        cvCircle( img, cvPoint(pt1.x, pt1.y), 3, CV_RGB(255, 128, 0), 3, 8, 0 );    
        cvCircle( img, cvPoint(box.center.x, box.center.y), 3, CV_RGB(75, 243, 243), 1, 8, 0 );
        cvEllipse( img, cvPoint(pt1.x, pt1.y), cvSize(box.size.height/2, box.size.width/2), box.angle, 0, 360, CV_RGB(220, 0, 120), 2, 8, 0 );
        cvDrawContours( Rhand, hand_contour,  CV_RGB( 0, 200, 100), CV_RGB( 100, 0, 0), 1, 1, 8, cvPoint(pt1.x,pt1.y));
        cvDrawContours( img, hand_contour,  CV_RGB( 0, 200, 100), CV_RGB( 100, 0, 0), 1, 1, 8, cvPoint(pt1.x,pt1.y));
        cvShowImage( "Rhand after draw contour", Rhand);
        cvShowImage( "img After draw contour", img);

        cvResetImageROI(Rhand);
        ///////////////////// End hand contour detection////////////////////////
}
// Draw the rectangle in the input image
 cvRectangle( img, pt1, pt2, CV_RGB(0,255,0), 3, 8, 0 );
}
cvClearSeq(handsO);
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

岁吢 2024-11-10 00:55:42

我不确定代码,因为我自己刚刚学习这个,但由于 cvConvexityDefect 为您提供了深度,您可以迭代所有缺陷并检查该值是否落在您期望的从指尖到手。您需要检查您的手,并根据您能看到的手指数量计算出有多少缺陷。

I'm not sure of the code since I'm just learning this myself but since the cvConvexityDefect gives you the depth you could iterate through all the defects and check that this value falls within the length you would expect from the tip of a finger to the hand. You'll need to look at your hand and work out how many defects there are depending on the amount of fingers you can see.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文