如何计算手指的数量? (openCV+轮廓检测)
我开始使用 findContour
查找手部轮廓,但是当我想使用 convHull2
和 convextyDefect
计算手指时,我不知道该怎么做。
请你帮助我好吗?这是我的代码:
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我不确定代码,因为我自己刚刚学习这个,但由于 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.