TUIO 예제 소스코드를 몇시간 분석 후 대충 어떻게 돌아가는지 공부했다.

C++ 예제 소스도 첨부~~ (당신의 시간은 소중하니깐... = > )








나는 키넥트의 스켈레톤을 이용하여 양손의 위치정보를 이용하여 멀티터치 기능을 구현해 보았다.

정작 7시간?? 이 걸렸다.

프로그래밍의 구조를 막 생각하다가..

나중에는 막코딩을 해서 지금 구조는 엉망인데,

다음주나 되서 리팩토링을 하여 좀 다시 구조를 잡아야 겠다.



동영상은 혼자 촬영하다보니 허접한데, 다시 조만간 촬영해야겠다.

(카메라 든손도 움직이다보니 화면보니깐 어질어질;;)

'[ Topics ] > TUIO' 카테고리의 다른 글

TUIO 시작 및 참조  (0) 2012.01.07
Posted by Tommy™
,




키넥트의 Skeleton 알고리즘은 공개되어있지 않다.

궁금하긴 하지만.. 당연 수학적인 요소들이 엄청나게 들어가있을꺼라 생각한다.

다음에 수학공부를 좀 더 해서 그때 파해쳐 봐야겠고... (이것만으로도 근데 논문 주제가 되겠다는 생각이...)



어째뜬 오늘은 SDK가 지원해주는 Skeleton 알고리즘을 이용하여 화면에 출력 해보았다.

함수는 NuiTransformSkeletonToDepthImageF(Vector4 vPoint, FLOAT *pfDepthX, FLOAT *pfDepthY) 를 이용하면 된다.

이함수는 각 관절의 위치를 얻어오는 함수인데, x,y 의 값을 얻어올수있다.

그런데 내가 원하는 데이터는 Z축 데이터 , 즉 깊이값!!

이는..

SkeletonPosition을 HRESULT NuiTransformSkeletonToDepthImageF(Vector4 vPoint, FLOAT *pfDepthX, FLOAT *pfDepthY, FLOAT *pfDepth) 

이 함수를 이용하면 얻어올수가 있는데,

각 Joint 마다 그 수치를 출력해봤는데, 매우 정확한듯했다.

키넥트.. 정말 잘만들고 정교하다......는걸 새삼 다시 느끼게 되었다.

말이 샜는데 어째뜬 이는 물론 키넥트 SDK 셈플소스에 추가되어있다.

(난 이것도 모르고 뻘짓을 몇시간동안이나...ㅠㅠ)

여기에는 매개변수가 총 3개가 들어가는데, 인터넷에서 검색해서 공부하고 찾아본 내용을 설명을 하자니.. 너무 광범위 하다.

그래서 블로그를 하나 소개 하겠다.


site : http://www.cyworld.com/krop_spiller/6824891

 

http://www.cyworld.com/krop_spiller (사이트 링크 수정 : 2012. 07.25)



여기인데, 알고보니 후배 블로그 였다는...

어째뜬 이곳에 가면 후배녀석이 아주 상세하고 자세하게 적어놓았다. (저도 여기서 공부했다는.. 헤헤 ^^;;)


이것은 나의 결과 스샷!!!

 

 



누군가가 도와줬으면 좋겠지만, 이때 연구실에 아무도 없었다는 ㅠㅠ

위에 보면 머리부분과 손이 가장 가까운데, 머리 부분을 보면 7560 이라 되어있다

이는 0.75m 가 떨어져있다는 소리겠지요??


참고로 나의 개발환경은..

Window 7 32bit,

Visual studio 2010

C++,  MFC

Kinect SDK 이다.

 

 

 

 

 

/*//////////////////////////////////////////////////////////////////////////

130923_추가.

//////////////////////////////////////////////////////////////////////////*/

 

소스코드를 보고싶어 하시는 분들이 많으셔서 업로드 하게 되었습니다.

 

그전에 말씀 드릴것은,

 

2012. 1. 6 에 만들었던 프로젝트 파일이며,

 

VS2010, OpenCV2.0, Kinect SDK beta2 버전입니다.

 

이사람은 이렇게 했었구나.. 라고만 참조하시면 좋을듯 합니다.

 

1년 반 전에 처음 키넥트SDK 가 나왔을때 공부목적으로 만든 소스코드라 엉망이라는점,

 

염두해주시면 감사하겠습니다. ^^

 

/*//////////////////////////////////////////////////////////////////////////

120106_Kinect_MFC(Depth, Skeleton with Z, depthdata).zip

//////////////////////////////////////////////////////////////////////////*/

 

 

 

 

Posted by Tommy™
,

최근 몇일동안 C++ 버전으로 되어있는 키넥트SDK 예제를 MFC로 한번 이식해서 만들어봐야겠다!! 라고 굳게 다짐하고,

프레임워크를 짰다가 맘에 안들어서 다시 지우고를 5번정도 했을때,

가장 맘에 드는 프레임 워크가 짜졌다.

그 구조는.. 간단히 말해서,



이렇게 인데, Kinect 클래스와 OpenCV 클래스를 각각 만든 후,

OpenCV 클래스 내부에서 Kinect 클래스를 동적할당하여 사용하는 방식이다.

(뭐 다른 좋은 방법도 있겠지만, 아직 보지못했고, 여러번 프레임워크를 짜면서 느낀점을 취합하여 선택한 구조라는... ㅠㅠ)

이방식의 장점은 내가 아주 사랑하고 애용하는 싱글턴 패턴 사용빈도를 확!! 줄일수있어서 성능이 향상 되었고,

또 Kinect 와 OpenCV 를 각각 클래스화 시켜서 관리하기 편하게 만들었기때문에 정리정돈도 잘된 느낌이다. (지극히 주관적인 생각 ^^;;)


어째뜬 이제 제일 중요한 쓰레드만 남기고 있는 상황이었는데, 여기서 문제가 터졌다.

Kinect Class 내부의 멤버함수를 Thread 생성해서 실행시키려니깐..

error C3867 에러가 뜬다.

응..??

"&CDebugger::DebugMessageLoop'을(를) 사용하여 멤버에 대한 포인터를 만드십시오."

이건 뭐지..??

그래서 검색해보니깐...

CreateThread() 함수에 넘겨줄 수 있는 함수는 다음과 같다고 한다.

1. Static 멤버 함수
2. 클래스 멤버가 아닌 함수

그러나, Static 멤버 함수로 선언을 하게되면.. 멤버 변수에 접근이 불가능하지 않은가..

다시 뭔가 불안감이 엄습해왔지만...

다른 방법이 꼭!! 꼭!! 반드시!! 있을거라 생각하고 좀더 검색해보자 마음을 먹고,

구글링을 해보다가 다음과 같은 상콤한 방법이 존재한다네요. 빠밤~~

그 방법은, static으로 ThreadProc를 선언하고, 이 함수의 인수로 this를 넘겨준 다음,

ThreadProc에서 인수를 클래스로 캐스팅해서 원하는 함수를 호출하면된다네요,

즉,

ThreadHandle = CreateThread(NULL, 0, ThreadProc, this, 0, NULL);

이렇게 Thread를 생성한 다음,

static DWORD WINAPI Foo::ThreadProc(LPVOID lParam)
{
  Foo *This = (Foo *)lParam;
  return This->Test();
}

void Foo::Test()
{
      printf("This is just Test!!\n");
}


흐흐 ~~~~ 그래서 완성~~!!


어째뜬 참고 하실분들은 참고하길...







이렇게 하여 Kinect SDK Sample C++ Source 를 MFC로 이식 완료!!

VS2010, MFC + OpenCV + KinectSDK


 

Posted by Tommy™
,

이번시간에는 Depth 카메라를 출력, 그리고 얻어진 Depth 값을 이용하여 거리에 따라 0~255값으로 바뀌게 해보겠습니다.

일단 먼저 저번시간에 했던 프로젝트를 다 다운받아주세요~

링크 : http://tommyhsm.tistory.com/entry/Tommys-Kinect-vol2-Kinect-SDK를-이용한-간단한-프로젝트

(아 또 친절하게 링크까지... 당연한건가?? -_ㅜ)



이번에는 image를 한개 더 가져와서 2개를 띄웁니다.



다음으로 RGB 카메라와 같이 설정을 해줍니다.

그런데 살짝 다릅니다.

같이 한번 볼까요??

Initialize 할때 UseDepth를 추가 해줍니다. (Depth 를 이용할꺼니깐요 -_- , 맨날 당연한소리만 하네요 하하 ㅋㅋ)

일단 레졸루션은 320 X 240 을 씁니다.

물론 640 X 480 으로 하셔도 상관없습니다. 그런데 최적화는 320 X 240 으로 되있으니 권장 하는대로 쓰겠습니다.

그리고 imagetype 을 depth 로 두고 합니다.

마지막으로 매 프레임마다 depth 값을 얻어올 함수를 이벤트 핸들러를 통해 등록해줍니다.


자 다음으로 메세지 핸들러에 추가되는 함수를 구현 해봅시다.

뭐 설정은 비슷합니다.

대신 여기서 유의하실점은 BGR32 가 아닌 Gray16을 쓴다는점, 16비트를 쓰기 떄문인데요, 이는 거리 화상 데이터 구조가 보통 16비트로 되있어서 이렇게 쓴다고 합니다. (저도 잘 몰라서 검색해서 알게된 사실..)



자 그럼 한번 출력 해볼까요?? ^^




나오긴 하는데.. 뭔가 Depth 영상이 시원찮네요;;

맘에 안들어 -_- 쳇..

그래서 0~255로 Normalize 시켜 봅시다.

일단 노멀라이즈 시키기 위해서는 거리를 알아야겠죠,

그 식이 아래와 같은데요, or 첫번째 영상 데이터와 두번째 영상 데이터중 두번째꺼를 시프팅 시켜서 비트연산을 하면 그 거리가 나온다고 하네요.

이건 저도 잘 몰라서 찾아보고 있는중입니다;; 혹시나 자료를 찾게 되면 다시 한번 올리겠습니다.



어째뜬 거리가 나오면 그 값을 이용하여 노멀라이즈 시키면 되겠지요 :)

이제는 노멀라이즈 시키는 부분입니다.

Byte array를 생성 해주고요~ (아 참고로 BGR32 를 쓸껍니다. 그래서 32bit 이기때문에 4바이트, 즉 *4를 더 해줍니다.)

그리고 노멀라이즈 시켜줍니다. 255 에서 나온 거리를 계산한 값과 연산함으로써 가까울수록 255, 멀수록 0 이 되겠습니다.

왜냐하면 BYTE는 unsigned char 즉, 0 ~ 255 만으로 값을 표현하는데, 영상처리에서 그레이 영상을 표현할때 이렇게 표현하지요 :)

(자세한건 영상처리 책에 아~~주 자세하게 설명 되어있습니다.)

배열 index와 r,g,b index를 이용하여 컬러 테이블을 만들어 줍니다.

그리하여 0 ~ 255 사이의 값으로 노멀라이즈 된 Byte array 가 완성 되었습니다.



마지막으로 이미지를 얻어와야겠죠,

위에서 언급한대로 bgr32 를 이용, 그리고 color table을 이미지영상으로 적용, 16비트 영상이기 때문에 *2 를 해줍니다.



이제 한번 구동 해볼까요??

Let's Start~!!


이제 좀 Depth 영상 같네 ㅋㅋㅋ 그죠잉??

근데 주의하셔야 할 사항이 있습니다.

최소한 50cm 정도는 떨어져야 제대로 된 영상이 나옵니다.

너무 가까우면 아예 검정색으로 나오는데, 이는 카메라 두개가 보는 시야에서 사라지기 때문이라고... 들었답니다.

그래서 검정색으로 표현되게....했다고 합니다.

(이놈의 습자지 지식 -_-;;;)


어째뜬 나는 그레이 영상이 싫타!! 좀 Colorful 하게 해보고 싶다, 이러한 분들은 조금만 응용해보시면 이렇게 하실수도 있겠네요 ^^

거리에 따라 R,G,B 색으로 바뀌게 해 보았습니다.

(조건문은 1500mm, 3000mm, 4500mm 으로 했습니다.)



이상으로 Depth 카메라를 이용하여 간단한 프로젝트를 진행 해보았습니다.

프로젝트 파일도 함께 첨부합니다.






사실 이번 블로깅까지는 저번에 준비해놨기때문에 빨리 빨리 진행이 되었는데,

다음번은 언제 올라올지 모르겠네요,

빠른 시일내에 더 공부하여 올리도록 하겠습니다.

조언이나 기타 다른 문의사항있으시면 언제든지 글남겨주세요 ^^

이상 Tommy 였습니다.

Posted by Tommy™
,

이번시간에는 C# - WPF를 이용하여 RGB 카메라를 한번 출력 해보겠습니다.

먼저 VS2010을 켜주시구요~ C#에서 WPF 응용 프로그램을 선택 제작~

만들고 나면...

이렇게 나오겠지요?? (당연하잖아 -_-;;)


이제 왼쪽 항목에 보면 '참조' 란이 있습니다.

저기서 우클릭, 참조추가를 하면 다이얼로그 박스가 하나 뜨는데, 거기서 ,Net 항목중 Microsoft.Research.Kinect 항목이 있습니다.

더블클릭하여 추가~!!



그리고 MainWindow.xaml.cs 를 더블클릭하여 using Microsoft.Research.Kinect.Nui; 를 입력 해줍니다.
(다들 using namespace 아실꺼라 생각합니다. 모르시는분은 다른 블로그 검색해보세요 , ^^;; 무책임하군 -_-)


다음으로 MainWindow.xaml로 가서 오른쪽 도구창에서 Image를 드래그 해서 놓아봅니다.

이곳은 이미지가 나올 창입니다.


다음으로 메인 윈도우 부분을 더블클릭하여 초기화를 할 부분인 Window_Loaded 함수를 만들어봅니다.



다음으로 키넥트 클래스명인 Runtime 확장자명으로 생성합니다. 저는 _Kinect 로 했습니다.

그리고 초기화를 해주는데요,

먼저 연결되어있는 키넥트번호를 설정, 그리고 RGB카메라를 이용할거라고 Initialize 해줍니다.

(참고로 RGB 카메라는 640 X 480 , Depth 카메라는 320 X 240 이 가장 최적화 되있다고 합니다. (어디서 줏어 들은거는 있어가지고 -_-) )

그리고 기본 레졸루션을 설정, 이벤트 핸들러를 통해 최종적으로 이미지가 불려질 함수를 지정 해줍니다.



다음은 영상을 매 프레임 얻어 줄 이벤트 함수 부분을 만듭니다.

역시나 필요한 정보들을 기입 하여 적어줍니다.

(척 보면 매개변수가 뭔지 대~충 눈으로 볼수 있겠죠??;; 아닌가??;;)




자~ 이렇게 해서 이제 RGB 카메라가 동작합니다 :)




프로젝트 파일도 함께 첨부합니다.


자 이제 한발자국 걸어왔습니다.

저도 공부하면서 진행하는거라 많이 느리고 설명이 미흡한면이 많을겁니다.

그런점은 겸허히 봐주시구요, 질타 언제든지 감사합니다 (__)


이상 Tommy 였습니다.

Posted by Tommy™
,