在 ubantu 下安装好 opencv 后就可以运行手势识别小程序了
#ifdef _CH_ #define WIN32 #error "The file needs cvaux, which is not wrapped yet. Sorry" #endif #ifndef _EiC #include "cv.h" #include "cvaux.h" #include "highgui.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #include <assert.h> #include <math.h> #include <float.h> #include <limits.h> #include <time.h> #include <ctype.h> #endif static CvMemStorage* storage; //static double color; static CvSize imgSize; static CvSeq* contour; static CvSeq* biggest; static CvCapture* capture = 0; static int isHandOpen = 1; static double color; static IplImage *img; static IplImage *tmpImg; static IplImage *conv; static IplImage *H; static IplImage *S; static IplImage *V; static IplImage *tmpH1; static IplImage *tmpS1; static IplImage *tmpH2; static IplImage *tmpH3; static IplImage *tmpS2; static IplImage *tmpS3; static IplImage *openHandTmpl, *closedHandTmpl; static IplImage *openGrayHandTmpl, *closedGrayHandTmpl; static IplImage *openscaledTmpl, *closedscaledTmpl; static IplImage *openMatchResult, *closedMatchResult; static IplConvKernel *erosionElement, *dilationElement; FILE *output; void handDetect( IplImage *img); static int numImg = 10; char *names[] = { "test01.jpg", "test02.jpg", "test03.jpg", "test04.jpg", "test05.jpg", "test06.jpg", "test07.jpg", "test08.jpg", "test09.jpg", "test10.jpg"}; int main( int argc, char** argv ) { int i = 0; char filename[80]; storage = cvCreateMemStorage(0); #ifdef DEBUG cvNamedWindow( "Template1", 1 ); cvNamedWindow( "Template2", 1 ); cvNamedWindow( "Comp Results1", 1 ); cvNamedWindow( "Comp Results2", 1 ); cvNamedWindow( "Skin Detection", 1 ); #endif cvNamedWindow( "Results", 1 ); cvAddSearchPath("\\images\\"); // Open the Output File output = fopen( "results.log", "w" ); // Color for contour drawing //color = CV_RGB( 255,255,255 ); if( argc == 1 || (argc == 2 && strlen(argv[1]) == 1 && isdigit(argv[1][0]))) { capture = cvCaptureFromCAM( argc == 2 ? argv[1][0] - ‘0‘ : 0 ); } else if( argc == 2 ) { capture = cvCaptureFromAVI( argv[1] ); } IplImage *frame, *frame_copy; frame = cvCreateImage(cvSize(640,480),IPL_DEPTH_8U, 3); frame_copy = cvCreateImage(cvSize(640,480),IPL_DEPTH_8U, 3); openHandTmpl = cvCreateImage(cvSize(150,150),IPL_DEPTH_8U, 3); closedHandTmpl = cvCreateImage(cvSize(150,150),IPL_DEPTH_8U, 3); openGrayHandTmpl = cvCreateImage( cvSize(150,150), IPL_DEPTH_8U, 1); closedGrayHandTmpl = cvCreateImage( cvSize(150,150), IPL_DEPTH_8U, 1); tmpImg = cvCreateImage(cvSize(640,480),IPL_DEPTH_8U, 3); conv = cvCreateImage( cvSize(640,480), IPL_DEPTH_8U, 3); tmpH1 = cvCreateImage( cvSize(640,480), IPL_DEPTH_8U, 1); tmpS1 = cvCreateImage( cvSize(640,480), IPL_DEPTH_8U, 1); tmpH2 = cvCreateImage( cvSize(640,480), IPL_DEPTH_8U, 1); tmpS3 = cvCreateImage( cvSize(640,480), IPL_DEPTH_8U, 1); tmpH3 = cvCreateImage( cvSize(640,480), IPL_DEPTH_8U, 1); tmpS2 = cvCreateImage( cvSize(640,480), IPL_DEPTH_8U, 1); H = cvCreateImage( cvSize(640,480), IPL_DEPTH_8U, 1); S = cvCreateImage( cvSize(640,480), IPL_DEPTH_8U, 1); V = cvCreateImage( cvSize(640,480), IPL_DEPTH_8U, 1); CvvImage pSrcImg1, pSrcImg2; //获取图像: pSrcImg1.Load("openHandTmpl.jpg"); //str为Cstring类型的图像文件名 openHandTmpl = pSrcImg1.GetImage(); //拷贝出pSrcImg的图像数据。 pSrcImg2.Load("closedHandTmpl.jpg"); //str为Cstring类型的图像文件名 closedHandTmpl = pSrcImg2.GetImage(); //拷贝出pSrcImg的图像数据。 // Structuring Element Generation dilationElement = cvCreateStructuringElementEx( 5,5,3,3, CV_SHAPE_RECT , 0 ); erosionElement = cvCreateStructuringElementEx( 5,5,3,3, CV_SHAPE_RECT , 0 ); if(capture != 0) { for(;;) { if( !cvGrabFrame( capture )) break; frame = cvRetrieveFrame( capture ); if( !frame ) break; imgSize.width = frame->width; imgSize.height = frame->height; //frame = cvCreateImage(imgSize,IPL_DEPTH_8U, 3); //frame_copy = cvCreateImage(imgSize,IPL_DEPTH_8U, 3); cvCopy(frame,frame_copy,NULL); //代替 pImg = cvCloneImage(pSrcImg); //pImg初始化时必须分配空间,否则上述函数不能执行。 //frame_copy = cvCloneImage( frame ); if ( capture ) { cvFlip(frame_copy, frame_copy, 0); } handDetect( frame_copy ); //cvShowImage("Results",frame_copy); if( cvWaitKey( 10 ) >= 0 ) break; } cvReleaseCapture( &capture ); } else { /* for ( i = 0; i < numImg; i++ ) { fprintf(output, "Image %i %s ************************\n", i+1, names[i]); strcpy(filename, "result_"); cvNamedWindow( names[i], 1 ); img = cvLoadImage(names[i],1); cvShowImage(names[i],img); if( img ) { imgSize.width = img->width; imgSize.height = img->height; handDetect( img ); strcat(filename, names[i]); cvSaveImage(filename, img); cvReleaseImage(&img); } } cvWaitKey(0); for ( i = 0; i < numImg; i++ ) { cvDestroyWindow( names[i]); } */ } cvReleaseImage(&frame);//// cvReleaseImage(&frame_copy); cvReleaseImage(&tmpImg);//// cvReleaseImage(&conv); cvReleaseImage(&H); cvReleaseImage(&S); cvReleaseImage(&V); cvReleaseImage(&tmpH1); cvReleaseImage(&tmpH2); cvReleaseImage(&tmpH3); cvReleaseImage(&tmpS1); cvReleaseImage(&tmpS2); cvReleaseImage(&tmpS3); cvReleaseImage(&openHandTmpl); cvReleaseImage(&closedHandTmpl); cvReleaseImage(&openGrayHandTmpl); cvReleaseImage(&closedGrayHandTmpl); cvReleaseStructuringElement(&dilationElement); cvReleaseStructuringElement(&erosionElement); pSrcImg1.Destroy(); pSrcImg2.Destroy(); fclose( output ); cvDestroyWindow( "Result"); #ifdef DEBUG cvDestroyWindow( "Template1"); cvDestroyWindow( "Template2" ); cvDestroyWindow( "Comp Results1" ); cvDestroyWindow( "Comp Results2" ); cvDestroyWindow( "Skin Detection" ); #endif return 0; } void handDetect( IplImage *img) { CvSize tmplSize; CvSize resultSize; double contArea, imgArea, maxRatio = 0.0; CvRect bndRect = cvRect(0,0,0,0); CvPoint pt1, pt2; float scaleFactor; CvScalar averageValue; int startCount = 0; int openCount = 0; int closedCount = 0; float openCompRatio = 0.0; float closedCompRatio = 0.0; float bestRatio = 0.0; imgArea = imgSize.width * imgSize.height; //////////////////////////////////////////////////////////////// //释放内存 //pSrcImg变量不需要每次释放,因为每次Load时是覆盖以前的内存区域。pSrcImgCopy 同样。不过在程序结束时要释放,以免产生内存泄露或者别人以为你忘了。 /////////////////////////////////////////////////////////////////// // Open Template files //openHandTmpl = cvLoadImage("openHandTmpl.jpg",1); //closedHandTmpl = cvLoadImage("closedHandTmpl.jpg",1); // Convert form RGB to GRAY tmplSize.width = openHandTmpl->width; tmplSize.height = openHandTmpl->height; cvCvtColor( openHandTmpl, openGrayHandTmpl, CV_BGR2GRAY ); tmplSize.width = closedHandTmpl->width; tmplSize.height = closedHandTmpl->height; cvCvtColor( closedHandTmpl, closedGrayHandTmpl, CV_BGR2GRAY ); // Generate processing images //tmpImg = cvCloneImage(img); ////////////////////////////////////////////////////////////// cvCopy(img,tmpImg,NULL); /////////////////////////////////////////////////////////////// // Flip the image if in capture mode //if ( capture ) //{ // cvFlip(img, img, 0); //} // Image Smoothing //cvSmooth(img,tmpImg,CV_BLUR,3,3); cvSmooth(img,img,CV_GAUSSIAN,3,3); // Convert to HSV cvCvtColor( tmpImg, conv, CV_BGR2HSV ); // Split to HSV planes cvCvtPixToPlane(conv,H,S,V,0); // Average Illumination averageValue = cvAvg( V , 0); fprintf(output, "Illumination Level = %f\n", averageValue.val[0]); // Detect skin tone Hues and Saturations // NOTE: Hue values need to be doubled for actual // Red to Orange Hue with High Saturation // Hue 0 to 28 degree and Sat 190 to 200 cvInRangeS(H,cvScalar(0.0,0.0,0,0),cvScalar(14.0,0.0,0,0),tmpH1); cvInRangeS(S,cvScalar(75.0,0.0,0,0),cvScalar(200.,0.0,0,0),tmpS1); cvAnd(tmpH1,tmpS1,tmpH1,0); // Red Hue with Low Saturation // Hue 0 to 26 degree and Sat 20 to 90 cvInRangeS(H,cvScalar(0.0,0.0,0,0),cvScalar(13.0,0.0,0,0),tmpH2); cvInRangeS(S,cvScalar(20.0,0.0,0,0),cvScalar(90.0,0.0,0,0),tmpS2); cvAnd(tmpH2,tmpS2,tmpH2,0); // Red Hue to Pink with Low Saturation // Hue 340 to 360 degree and Sat 15 to 90 cvInRangeS(H,cvScalar(170.0,0.0,0,0),cvScalar(180.0,0.0,0,0),tmpH3); cvInRangeS(S,cvScalar(15.0,0.0,0,0),cvScalar(90.,0.0,0,0),tmpS3); cvAnd(tmpH3,tmpS3,tmpH3,0); // Combine the Hue and Sat detections cvOr(tmpH3,tmpH2,tmpH2,0); cvOr(tmpH1,tmpH2,tmpH1,0); // Dilation and Erosion // Dilation adds a layer on, and returns things to the correct size. cvDilate(tmpH1,tmpH2,dilationElement,1); // Erosion peels a layer of pixels off, and makes small regions disappear cvErode(tmpH1,tmpH3,erosionElement,1); // Find the contours of all remaining objects contour = 0; biggest = 0; cvFindContours( tmpH3, storage, &contour, sizeof(CvContour), CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE ); cvZero(tmpH1); // contour now contains a CvSequence of all of the contours for( ; contour != 0; contour = contour->h_next ) { contArea = fabs(cvContourArea( contour, CV_WHOLE_SEQ )); // Ignore very small contours if ( contArea/imgArea >= 0.015 ) { cvDrawContours( tmpH1, contour, CV_RGB( 255,255,255 ), CV_RGB( 255,255,255 ), 0, -1, 8 ); bndRect = cvBoundingRect( contour, 0 ); // Scale the templates and result images scaleFactor = ((float)bndRect.width / (float)openHandTmpl->width); tmplSize.width = scaleFactor * openHandTmpl->width; tmplSize.height = scaleFactor * openHandTmpl->height; openscaledTmpl = cvCreateImage( tmplSize, IPL_DEPTH_8U, 1); closedscaledTmpl = cvCreateImage( tmplSize, IPL_DEPTH_8U, 1); openMatchResult = cvCreateImage( tmplSize, IPL_DEPTH_8U, 1); closedMatchResult = cvCreateImage( tmplSize, IPL_DEPTH_8U, 1); cvResize( openGrayHandTmpl,openscaledTmpl, CV_INTER_LINEAR ); cvResize( closedGrayHandTmpl,closedscaledTmpl, CV_INTER_LINEAR ); // Set ROI for image bndRect.width = tmplSize.width; bndRect.height = tmplSize.height; cvSetImageROI(tmpH1, bndRect); // Check that ROI matches the tmplate sizes // If the ROI is too near the edge og the image then the // ROI may be truncated when it is set and will not match the bndRect if ( tmpH1->roi->width != bndRect.width || tmpH1->roi->height != bndRect.height ) { } else { // Compare the Templates to the image ROI cvCmp( tmpH1,openscaledTmpl, openMatchResult, CV_CMP_EQ ); cvCmp( tmpH1,closedscaledTmpl, closedMatchResult, CV_CMP_EQ ); } // Analyze the results startCount = cvCountNonZero( tmpH1 ); openCount = cvCountNonZero( openMatchResult ); closedCount = cvCountNonZero( closedMatchResult ); openCompRatio = (float)openCount/(float)startCount; closedCompRatio = (float)closedCount/(float)startCount; bestRatio = 0.0; // Small regions may give eroneous results if ( openCompRatio > 1.0 ) openCompRatio = 0.0; if ( closedCompRatio > 1.0 ) closedCompRatio = 0.0; // Compare the Open and closed hand results if ( openCompRatio > closedCompRatio ) { if ( openCompRatio > maxRatio ) { maxRatio = openCompRatio; biggest = contour; isHandOpen = 1; } } else { if ( closedCompRatio > maxRatio ) { maxRatio = closedCompRatio; biggest = contour; isHandOpen = 0; } } // Reset ROI cvResetImageROI( tmpH1 ); // Output the results fprintf(output, "Contour Non-zero Count = %i\n", startCount); fprintf(output, "Open Hand Matched Non-zero Count = %i Open Hand Ratio = %f\n", openCount, openCompRatio); fprintf(output, "Clased Hand Matched Non-zero Count = %i Clased Hand Ratio = %f\n\n", closedCount, closedCompRatio); #ifdef DEBUG cvShowImage("Comp Results1",openMatchResult); cvShowImage("Comp Results2",closedMatchResult); cvShowImage("Template1",openscaledTmpl); cvShowImage("Template2",closedscaledTmpl); cvShowImage("Skin Detection",tmpH1); cvWaitKey(0); #endif cvReleaseImage(&openscaledTmpl); cvReleaseImage(&closedscaledTmpl); cvReleaseImage(&openMatchResult); cvReleaseImage(&closedMatchResult); } cvZero(tmpH1); } // Draw Detection Rectangle // Red for Open Hand // Green for Closed Hand if ( biggest && maxRatio > 0.50 ) { bndRect = cvBoundingRect( biggest, 0 ); cvResetImageROI( img ); pt1.x = bndRect.x; pt1.y = bndRect.y; pt2.x = bndRect.x + bndRect.width; pt2.y = bndRect.y + bndRect.height; if ( isHandOpen ) { cvRectangle( img, pt1, pt2, CV_RGB(255,0,0), 5 ); } else { cvRectangle( img, pt1, pt2, CV_RGB(0,255,0), 5 ); } } // Display the results cvShowImage("Results",img); // If we found any contours then free the memory they use. if (contour!=NULL) { cvClearSeq(contour); } } #ifdef _EiC main(1,"HandDetect.c"); #endif
编译 g++ camshift.cpp -o camshift
运行 ./camshift
效果图片竟然上传不了,代码和图片资源在我上传的资源那边,想要的可以去我的资源那边下载