在 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
效果图片竟然上传不了,代码和图片资源在我上传的资源那边,想要的可以去我的资源那边下载