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

C++ 如何计算手指的数量?(openCV+;轮廓检测),c++,visual-studio-2008,opencv,computer-vision,contour,C++,Visual Studio 2008,Opencv,Computer Vision,Contour,我开始用findContour查找手的轮廓,但当我想用convHull2和convxtydefect计算手指时,我不知道该怎么办 你能帮帮我吗?这是我的密码: if( cascade1 ) { static CvMemStorage* storage4 = 0; static CvMemStorage* storage5 = 0; static CvMemStorage* storage6 = 0; static CvMemStorage* storage7 = 0; CvSeq* cont

我开始用
findContour
查找手的轮廓,但当我想用
convHull2
convxtydefect
计算手指时,我不知道该怎么办

你能帮帮我吗?这是我的密码:

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);
}
if(级联1)
{
静态CvMemStorage*storage4=0;
静态CvMemStorage*storage5=0;
静态CvMemStorage*storage6=0;
静态CvMemStorage*storage7=0;
CvSeq*等高线;
CvSeq*手部轮廓=空;
//一张图片中可以有多只手,所以创建一个可扩展的手序列。
//检测对象并按顺序存储它们
CvSeq*handsO=cvhaardeticobjects(img、cascade1、storage1、1.1、2、CV_HAAR_DO_CANNY_修剪、cvSize(40,40));
storage4=cvCreateMemStorage(0);
storage5=cvCreateMemStorage(0);
storage6=cvCreateMemStorage(0);
storage7=cvCreateMemStorage(0);
cvClearMemStorage(storage4);
cvClearMemStorage(storage5);
cvClearMemStorage(storage6);
cvClearMemStorage(storage7);
//循环找到的手数。
对于(i=0;i<(握手?握手->总计:0);i++)
{
//创建用于绘制手的新矩形
CvRect*r=(CvRect*)cvgetsekelem(handsO,i);
//找到手的尺寸,必要时进行缩放
pt1.x=r->x*刻度;
pt2.x=(r->x+r->宽度)*比例;
pt1.y=r->y*刻度;
pt2.y=(r->y+r->高度)*刻度;
/////////////////////开始手轮廓检测////////////////////////
//找到手后,将其设置为图像的内部区域,这样之后的所有功能将仅适用于该区域
cvSetImageROI(Rhand,cvRect(r->x*比例,r->y*比例,r->宽度*比例,r->高度*比例));
/*
/为findContour函数准备图像
/1-将其转换为灰色
/2-打谷
/3-找到边缘
*/
cvShowImage(“灰手”,Rhand);
cvThreshold(Rhand,Rhand,1255,CV_THRESH_二进制);
cvShowImage(“阈值手”,Rhand);
cvCanny(Rhand,Rhand,1,3,5);
cvShowImage(“边缘手”,Rhand);
/*
//关闭阈值后测试是否会有更好的结果
IplConvKernel*内核=0;
kernel=cvCreateStructuringElementEx(5,5,0,0,CV_-SHAPE_-RECT);
CvExplate(Rhand,Rhand,kernel,1);
CVE侵蚀(Rhand,Rhand,内核,1);
*/
//查找图像中的所有轮廓
cvFindContours(Rhand、storage4和contours、sizeof(CvContours)、CV_RETR_列表、CV_CHAIN_近似值、cvPoint(0,0));
//printf(“\n行程数量%d”,等高线->总计);
//找到最简单的轮廓,并将每个轮廓的面积进行比较,使其成为手
双面积=0,大面积=0;
while(等高线)
{
面积=晶圆厂(等高线面积(等高线,等高线整体);
//printf(“n\\\\\\\\\\\%f”,面积);
如果(面积>大面积)
{
大面积=面积;
手部轮廓=轮廓;
//printf(“\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\;
};
轮廓=轮廓->h_下一步;
}
cvWaitKey(0);
if(手部轮廓)
{
手形轮廓=CVAPROXPOLY(手形轮廓,尺寸(CVCONTOURE),存储7,CV POLY近似DP,3,1);
CvRect rect=cvBoundingRect(手部轮廓,1);
CvBox2D box=CVMINAREACT2(手部轮廓,存储6);
//围绕轮廓绘制矩形
cvRectangle(img,cvPoint(rect.x,rect.y+rect.height),cvPoint(rect.x+rect.width,rect.y),CV_RGB(255,255,0),1,8,0);
//准备检测手指并计算/绘制它们
CvSeq*外壳=CVCONVERXHULL2(手形轮廓,0,顺时针,0);
int numohull=hull->total;
CvPoint*外壳点;
外壳点=(CvPoint*)malloc((外壳->总)*尺寸(CvSeq));
CVTSEQTOARRAY(船体、船体点);
CvSeq*缺陷=CV凸度缺陷(手形轮廓、船体、仓库5);
int numOfdefect=缺陷->总计;
CvConvexityDefect*缺陷阵列;
defectArray=(cvconverxitydefect*)malloc(sizeof(cvconverxitydefect)*numofdefect);
CVTSEqToArray(缺陷,缺陷阵列);
/*int h1,h2;

对于(i=0;i我不确定代码,因为我只是自己学习这一点,但由于CVConverxityDefect提供了您可以迭代所有缺陷的深度,并检查该值是否在从指尖到手的预期长度范围内。您需要查看您的手,计算出有多少缺陷你可以假设一只手的手指数是五个。使用此代码,你会有很高的准确性:
int CountFingers(cv::Mat&img){return 5;}