轉載:http://blog.csdn.net/chenxin_130/article/details/6703301
小斤的部落格貼出了源碼,手勢識别
轉載:http://viml.nchc.org.tw/blog/paper_info.php?CLASS_ID=1&SUB_ID=1&PAPER_ID=234
heresy大神較長的描述了原理
通過函數 xn::GestureGenerator 的函式EnumerateGestures() 來取得可識别手勢名稱。
#include <stdlib.h>
#include <iostream>
#include "opencv/cv.h"
#include "opencv/highgui.h"
#include <XnCppWrapper.h>
using namespace std;
using namespace cv;
// output for XnPoint3D
ostream& operator<<( ostream& out, const XnPoint3D& rPoint )
{
out << "(" << rPoint.X << "," << rPoint.Y << "," << rPoint.Z << ")";
return out;
}
//【4】手勢識别callback 函數,可為空
// callback function for gesture recognized
void XN_CALLBACK_TYPE gestureRecog( xn::GestureGenerator &generator,
const XnChar *strGesture,
const XnPoint3D *pIDPosition,
const XnPoint3D *pEndPosition,
void *pCookie )
{
cout << strGesture<<" from "<<*pIDPosition<<" to "<<*pEndPosition << endl;
//畫出手勢識别時的點
int imgStartX=0;
int imgStartY=0;
int imgEndX=0;
int imgEndY=0;
char locationinfo[100];
imgStartX=(int)(640/2-(pIDPosition->X));
imgStartY=(int)(480/2-(pIDPosition->Y));
imgEndX=(int)(640/2-(pEndPosition->X));
imgEndY=(int)(480/2-(pEndPosition->Y));
IplImage* refimage=(IplImage*)pCookie;
if(strcmp(strGesture,"RaiseHand")==0)
{
cvCircle(refimage,cvPoint(imgStartX,imgStartY),1,CV_RGB(255,0,0),2);
}
else if(strcmp(strGesture,"Wave")==0)
{
cvLine(refimage,cvPoint(imgStartX,imgStartY),cvPoint(imgEndX,imgEndY),CV_RGB(255,255,0),6);
}
else if(strcmp(strGesture,"Click")==0)
{
cvCircle(refimage,cvPoint(imgStartX,imgStartY),6,CV_RGB(0,0,255),12);
}
cvSetImageROI(refimage,cvRect(40,450,640,30));
CvFont font;
cvInitFont( &font, CV_FONT_VECTOR0,1, 1, 0, 3, 5);
cvSet(refimage, cvScalar(255,255,255));
sprintf(locationinfo,"From: %d,%d to %d,%d",(int)pIDPosition->X,(int)pIDPosition->Y,(int)(pEndPosition->X),(int)(pEndPosition->Y));
cvPutText(refimage, locationinfo ,cvPoint(30, 30), &font, CV_RGB(0,0,0));
cvResetImageROI(refimage);
}
void clearImg(IplImage* inputimg)
{
CvFont font;
cvInitFont( &font, CV_FONT_VECTOR0,1, 1, 0, 3, 5);
memset(inputimg->imageData,255,640*480*3);
cvPutText(inputimg, "Hand Raise!" ,cvPoint(20, 20), &font, CV_RGB(255,0,0));
cvPutText(inputimg, "Hand Wave!" , cvPoint(20, 50), &font, CV_RGB(255,255,0));
cvPutText(inputimg, "Hand Push!" , cvPoint(20, 80), &font, CV_RGB(0,0,255));
}
//【5】手勢過程callback
// callback function for gesture progress
void XN_CALLBACK_TYPE gestureProgress( xn::GestureGenerator &generator,
const XnChar *strGesture,
const XnPoint3D *pPosition,
XnFloat fProgress,
void *pCookie )
{
cout << strGesture << ":" << fProgress << " at " << *pPosition << endl;
}
int main( int argc, char** argv )
{
IplImage* drawPadImg=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,3);
IplImage* cameraImg=cvCreateImage(cvSize(640,480),IPL_DEPTH_16U,1);
IplImage* depthshow = cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
cvNamedWindow("Gesture",1);
cvNamedWindow("Camera",1);
clearImg(drawPadImg);
XnStatus res;
char key=0;
// context初始化context
xn::Context context;
res = context.Init();
xn::DepthMetaData depthMD;
// create generator 生産節點
// xn::ImageGenerator imageGenerator;
xn::DepthGenerator depthGenerator;
//res = imageGenerator.Create( context );
res = depthGenerator.Create(context);
//【1】
xn::GestureGenerator gestureGenerator;
res = gestureGenerator.Create( context );
/*檢查有多少種手勢
XnUInt16 uNum = 10;
XnChar** asName = new XnChar*[uNum];
for (int i=0; i<uNum;i++) {
asName[i] = new XnChar[100];
}
res = gestureGenerator.EnumerateGestures(*asName,uNum);
cout<<"there are"<<uNum<<"gestures"<<endl;
for (int i=0;i<uNum;i++) {
cout<<asName[i]<<endl;
}*/
//【2】設定手勢
// Add gesture
//gestureGenerator.AddGesture( "MovingHand", NULL );
gestureGenerator.AddGesture( "Wave", NULL );
gestureGenerator.AddGesture( "Click", NULL );
// gestureGenerator.AddGesture( "RaiseHand", NULL );
// gestureGenerator.AddGesture("MovingHand",NULL);
// /【3】callback函數
// 6. Register callback functions of gesture generator
XnCallbackHandle handle;
gestureGenerator.RegisterGestureCallbacks( gestureRecog, gestureProgress, (void*)drawPadImg, handle );
//start generate data
context.StartGeneratingAll();
res = context.WaitAndUpdateAll();
while( (key!=27) && !(res = context.WaitAndUpdateAll()) )
{
if(key=='c')
{
clearImg(drawPadImg);
}
depthGenerator.GetMetaData(depthMD);
memcpy(cameraImg->imageData,depthMD.Data(),640*480*2);
cvConvertScale(cameraImg,depthshow,255/4096.0,0);
cvShowImage("Gesture",drawPadImg);
cvShowImage("Camera",depthshow);
key=cvWaitKey(20);
}
cvDestroyWindow("Gesture");
cvDestroyWindow("Camera");
cvReleaseImage(&drawPadImg);
cvReleaseImage(&cameraImg);
context.StopGeneratingAll();
context.Shutdown();
return 0;
}