2011-04-21 100 views
2

我开始用findContour找到手部轮廓,但是当我想用convHull2convextyDefect来计算手指时,我不知道该怎么做。如何计算手指的数量? (openCV +轮廓检测)

你能帮我吗?这里是我的代码:

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); 
} 
+0

你可以假设一只手的手指数是五。你会有这个代码很好的准确性:'int CountFingers(cv :: Mat&img){return 5; }' – Sam 2013-02-11 07:14:03

回答

1

我不知道的代码,因为我刚学这个自己,但由于cvConvexityDefect给你深度,你可以通过所有的缺陷进行迭代,并检查该值落入从手指尖到手的距离。你需要看看你的手,并根据你可以看到的手指数量计算出有多少缺陷。