
키넥트에는 2개의 카메라(센서)가 있는데, 하나는 일반 웹캠과 같은 것이고,
다른 하나는 픽셀마다의 깊이(Depth)값을 전송하는 일종의 리얼타임(30fps) 3D스캐너로서,
영상을 이루는 픽셀이 카메라로부터 얼마나 먼 곳에 있는지를 알려준다.
키넥트는 이 두 가지 센서를 이용하여 사람의 눈처럼 게이머의 신체를 인식하기 때문에
조이스틱과 같은 물리적인 컨트롤러 없이 게임을 할 수 있다.

[사진] 키넥트가 깊이값을 인식하기 위해 레이저를 뿌린 것을 적외선 찰영한 것.
키넥트의 공개는 (게임 분야에서도 각광을 받았지만)
인터페이스/인터랙션 분야에서 열광적인 환영을 받았다.
특히 OpenNI 같은 오픈소스 덕분에 실험적 사례들이 쏟아져 나왔고,
결국 마이크로소프트에서 SDK를 공개하게 되었다.
OpenNI 보다 마이크로소프트 키넥트 SDK가 월등한 것은 아니고 장단점이 있다.
OpenNI의 가장 큰 단점은 사람을 인식할 때 역기 드는 자세를 잠시 취해야 하는 점이다.
마이크로소프트 키넥트 SDK는 바로 인식이 된다.
-
키넥트 공부를 미루다가 방학 시작하면서 OpenNI로 공부를 시작했다.
2주 정도 걸려서 OpenNI로 작업환경을 갖추었더니 마이크로소프트에서 SDK를 공개해서
다시 2주 동안 프로그래밍 가이드를 읽고 샘플코드를 분석했다.
OpenNI는 설치가 약간 번거롭지만, 깊이값을 받는 것은 단순하다.
반대로 MS의 SDK는 설치는 쉽지만 샘플코드가 (전산을 전공하지 않은 사람으로서는)
너무 복잡하고 깊이값을 읽는 것이 어려웠다.
C언어 기본서에서 포인터 부분을 읽으면서 해법을 찾았고 다행히 값을 읽어낼 수 있었다.
-
키넥트로부터 값을 받는 방식에는 2가지가 있다.
하나는 어플리케이션이 값을 요청하는 것이고(Polling),
다른 하나는 프레임이 준비가 되면 이벤트를 발생시키는 방식이다.
키넥트의 skeletalViiewer 샘플코드는 이벤트 모델을 사용한 것으로,
thread를 따로 만들어서 이곳에서 프레임 이벤트를 처리한다.
내가 사용해온 코드는 윈도우 프로시져(WndProc)에서 선언된 타이머를 사용하여 루프를 작동시킨다.
문제는 WndProc에서 실행되는 함수에서 프레임 데이터을 저장하는 메모리(LockedRect.pBits)에 접근하면
에러가 발생하는 것이었다. (이벤트 발생시점에 메모리에 접근해서 생기는 문제로 보인다.)
이 문제를 해결하기 위하여 CSkeletalViewer 오브젝트를 초기화할 때 WndProc(의 루프)에서 실행되는
함수A의 포인터를 CSkeletalViewer 오브젝트에 보내고,
CSkeletalViewer에서 프레임 이벤트가 발생될 때 함수A를 실행하도록 하였다.
함수는 아래와 같다.
void kinectVideo(BYTE * pBit){
memcpy(pKinectRGB, pBit, 640*480*4);
}
결과적으로 프레임 이벤트가 발생할 때 프레임 값을 (안전한) pKinectRGB로 옮기고 pKinectRGB에서 값을 얻는 것이다.
프레임 이벤트는 30fps이기 때문에 여기에 이미지 처리를 맞추는 것은 좋지 않고,
WndProc의 루프에서 이미지를 처리하는 것이 좋다고 생각한다.
WndProc과 프레임 이벤트를 처리하는 thread가 병렬로 실행되는 형식이라서 작업의 선후가 어떻게 되는지 궁금하다.
-
(2011.9.7.)
user index를 사용할 때와 안 할 때, depth값이 다르게 들어 오는데, 문서에 여기에 대한 설명이 없다.
문서에는 user index를 사용하지 않으면 (user index가 들어 있는) depth값이 저장된 메모리의
오른쪽 3비트에 0이 들어간다고 되어 있다.
실험을 해보니 user index를 사용하지 않으면 0이 들어가는 것이 아니고,
오른쪽 3비트에서부터 depth값이 들어가고 있다.
따라서 비트 쉬프팅(>>3)을 하지 않고 값을 받으면 user index를 사용할 때와 같은 값이 들어온다.
(화면 출력을 해보았을 때 값이 동일한 것으로 판단됨)

덧글