티스토리 뷰

음.. SkeletonStream을 뽑아내는데 대해서 많은 분들이 어려움을 겪으시네요. 특히 HANDLE 부분이 초기화가 되지 않는다고 하시는 분들이 많으신거 같은데요.

그래서 아예 전체 코드를 공개해드립니다. 동작영상도 보여드리니까 아마 코드 그대로 넣으시고 Linker 같은 dependency만 제대로 연결 잘하시면 아마 잘 되실 겁니다.


// SkeletonStream을 화면에 출력하기 위한 header 

#include <opencv/cv.h>

#include <opencv/highgui.h>

#include <opencv/cxcore.h>


//HANDLE을 쓰기 위한 window관련 header

#include <tchar.h>

#include <Windows.h>

#include <NuiApi.h>  // Microsoft Kinect SDK


//STL

#include <stdio.h>

#include <iostream>


using namespace std;

using namespace cv;


#define COLOR_WIDTH 640

#define COLOR_HEIGHT 480


CvPoint points[NUI_SKELETON_POSITION_COUNT];


void InitializeKinect();

int createRGBImage(HANDLE h, IplImage* Color);

void drawSkeleton(const NUI_SKELETON_DATA &position, IplImage *Skeleton);

void createSkeleton(IplImage*Skeleton);

CvPoint SkeletonToScreen(Vector4 skeletonPoint);

void drawBone(const NUI_SKELETON_DATA &position, NUI_SKELETON_POSITION_INDEX j1, NUI_SKELETON_POSITION_INDEX j2, IplImage *Skeleton);


void InitializeKinect()  // 키넥트 초기화 함수 

{

bool FailToConnect;

do

{

HRESULT hr = NuiInitialize(NUI_INITIALIZE_FLAG_USES_COLOR | NUI_INITIALIZE_FLAG_USES_SKELETON);  // NuiApi.h에서 불러온 함수가 처음 등장함


if(FAILED(hr))

{

system("cls");

cout<<"\nFailed to Connect!\n\n";

FailToConnect = true;

system("PAUSE");

}

else

{

cout<<"\nConnection Established!\n\n";

FailToConnect=false;

}

}

while(FailToConnect);

}





int createRGBImage(HANDLE h, IplImage* Color) 

{

const NUI_IMAGE_FRAME *pImageFrame = NULL;


HRESULT hr = NuiImageStreamGetNextFrame(h,1000,&pImageFrame);


if(FAILED(hr))

{

cout<<"Create FGB Image Failed\n";

return -1;

}


INuiFrameTexture *pTexture=pImageFrame->pFrameTexture;

NUI_LOCKED_RECT LockedRect;

pTexture->LockRect(0,&LockedRect,NULL,0);


if(LockedRect.Pitch !=0)

{

BYTE* pBuffer = (BYTE*)LockedRect.pBits;

cvSetData(Color, pBuffer,LockedRect.Pitch);

cvShowImage("Color Image", Color);

}


NuiImageStreamReleaseFrame(h,pImageFrame);

return 0;

}


void drawSkeleton(const NUI_SKELETON_DATA &position, IplImage *Skeleton)

{

for(int i =0; i<NUI_SKELETON_POSITION_COUNT;++i)

{

points[i]=SkeletonToScreen(position.SkeletonPositions[i]);

}



drawBone(position,NUI_SKELETON_POSITION_SHOULDER_RIGHT, NUI_SKELETON_POSITION_ELBOW_RIGHT,Skeleton);

drawBone(position,NUI_SKELETON_POSITION_ELBOW_RIGHT,NUI_SKELETON_POSITION_WRIST_RIGHT,Skeleton);

drawBone(position,NUI_SKELETON_POSITION_WRIST_RIGHT,NUI_SKELETON_POSITION_HAND_RIGHT,Skeleton);



drawBone(position,NUI_SKELETON_POSITION_SHOULDER_LEFT, NUI_SKELETON_POSITION_ELBOW_LEFT, Skeleton);

drawBone(position,NUI_SKELETON_POSITION_ELBOW_LEFT, NUI_SKELETON_POSITION_WRIST_LEFT, Skeleton);

drawBone(position,NUI_SKELETON_POSITION_WRIST_LEFT, NUI_SKELETON_POSITION_HAND_LEFT, Skeleton);



}


void createSkeleton(IplImage*Skeleton)

{

NUI_SKELETON_FRAME skeletonFrame ={0};

IplImage *Skeleton_clear = cvCreateImage(cvSize(COLOR_WIDTH,COLOR_HEIGHT), IPL_DEPTH_8U,4);

cvCopy(Skeleton_clear, Skeleton);


HRESULT hr=NuiSkeletonGetNextFrame(0,&skeletonFrame);

if(FAILED(hr))

{

return;

}


NuiTransformSmooth(&skeletonFrame,NULL);

for(int i=0; i<NUI_SKELETON_COUNT;i++)

{

NUI_SKELETON_TRACKING_STATE state=skeletonFrame.SkeletonData[i].eTrackingState;


if(NUI_SKELETON_TRACKED == state)

{

drawSkeleton(skeletonFrame.SkeletonData[i],Skeleton);

}


cvShowImage("Skeleton Image", Skeleton);


}


cvReleaseImage(&Skeleton_clear);

}





CvPoint SkeletonToScreen(Vector4 skeletonPoint)

{

LONG x,y;

USHORT depth;

NuiTransformSkeletonToDepthImage(skeletonPoint, &x, &y, &depth,NUI_IMAGE_RESOLUTION_640x480);


float screenPointX = static_cast<float>(x);

float screenPointY = static_cast<float>(y);


return cvPoint(screenPointX, screenPointY);

}



void drawBone(const NUI_SKELETON_DATA &position, NUI_SKELETON_POSITION_INDEX j1, NUI_SKELETON_POSITION_INDEX j2, IplImage *Skeleton)

{

NUI_SKELETON_POSITION_TRACKING_STATE j1state = position.eSkeletonPositionTrackingState[j1];

NUI_SKELETON_POSITION_TRACKING_STATE j2state = position.eSkeletonPositionTrackingState[j2];


if(j1state == NUI_SKELETON_POSITION_TRACKED && j2state == NUI_SKELETON_POSITION_TRACKED)

{

cvLine(Skeleton,points[j1],points[j2],CV_RGB(255,0,0),3,8,0);

}

}



int _tmain(int argc, _TCHAR* argv[])   // 메인함수 시작 

{

HANDLE colorStreamHandle;

HANDLE nextColorFrameEvent = CreateEvent(NULL, TRUE, FALSE, NULL);


HANDLE nextSkeletonFrameEvent = CreateEvent(NULL, TRUE, FALSE, NULL);


HRESULT hr;


InitializeKinect();

IplImage *Color=cvCreateImage(cvSize(COLOR_WIDTH,COLOR_HEIGHT),IPL_DEPTH_8U,4);

IplImage *Gray=cvCreateImage(cvSize(COLOR_WIDTH,COLOR_HEIGHT),IPL_DEPTH_8U,1);

IplImage *Skeleton=cvCreateImage(cvSize(COLOR_WIDTH,COLOR_HEIGHT),IPL_DEPTH_8U,4);


cvNamedWindow("Color Image",CV_WINDOW_AUTOSIZE);

cvNamedWindow("Skeleton Image",CV_WINDOW_AUTOSIZE);


hr=NuiImageStreamOpen(NUI_IMAGE_TYPE_COLOR, NUI_IMAGE_RESOLUTION_640x480,0,2,nextColorFrameEvent,&colorStreamHandle);


if(FAILED(hr))

{

cout<<"Could not open ImageStream"<<endl;

return hr;

}


hr=NuiSkeletonTrackingEnable(nextSkeletonFrameEvent,0);


if(FAILED(hr))

{

cout<<"Could not open SkeletonStream"<<endl;   // endl I? 뭐지?

return hr;

}


while(1)    // 종료후 키넥트 꺼주는 과정 

{

WaitForSingleObject(nextColorFrameEvent,1000);

createRGBImage(colorStreamHandle,Color);


WaitForSingleObject(nextSkeletonFrameEvent,0);

createSkeleton(Skeleton);


cvCvtColor(Color,Gray,CV_RGBA2GRAY);


cvShowImage("Gray Image",Gray);



if(cvWaitKey(10)==0x001b)

{

break;

}


}

NuiShutdown();   


cvReleaseImageHeader(&Color);

cvReleaseImage(&Gray);


cvDestroyAllWindows();

return 0;



}


동작 영상은 다음과 같습니다.



보니까 제가 했을 때 됬던게 다시 해보니까 안되는게 있는 듯 합니다. 아무튼 골격을 이용하실 분은 이 코드 사용하시면 될듯 하네요. 원글도 수정하겠습니다.

댓글