2
我开始用findContour
找到手部轮廓,但是当我想用convHull2
和convextyDefect
来计算手指时,我不知道该怎么做。如何计算手指的数量? (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);
}
你可以假设一只手的手指数是五。你会有这个代码很好的准确性:'int CountFingers(cv :: Mat&img){return 5; }' – Sam 2013-02-11 07:14:03