티스토리 뷰

지난 시간에는 Kinect가 들어가지는 않지만 3차원 공간을 생성하고 그안에서 Camera View를 컨트롤 할 수 있는 KinectOrbit이라는 것을 다뤄봤습니다. 이번 포스트에서는 실제로 KinectOrbit을 사용해서 Kinect를 이용할 수 있는 Kinect Space를 생성해보고자 합니다. 우선 SimpleOpenNI 라이브러리에 들어있는 예제를 살펴보겠습니다. 

정상적으로 설치하셨다면 Files 메뉴 항목에 Examples 라는 항목이 있을겁니다. 그걸 선택하면 새로운 창이 형성되는데 제일 밑에 내려가 보면 SimpleOpenNI 예제가 있습니다. 그중에서 DepthMap3D를 한번 보겠습니다.



그걸 실행시키면 다음과 같은 영상을 얻게 됩니다.



이 예제에서 가장 중요한 부분은 아래 코드입니다.



우선 3차원 상에서 depth Map을 그리기 위해서는 위와 같이 배열상에 저장해야 합니다. 프로세싱의 실행창 하나하나가 Pixel이고 그 것과 depth를 매핑을 하려면 배열이 필요한 것이겠지요. 하지만 지난 시간에도 언급한 것처럼 1차원 배열이기 때문에 그 하나하나의 픽셀을 찾아가기 위해서는 index를 찾는 방법이 중요하고 index를 구하는 방법은 잠깐 소개해드렸지요. 위에 코드에도 나와있습니다. 그래서 각각의 width나 height 를 step 만큼 늘리면서 해당 배열의 index에 들어있는 depthValue를 뽑아내게 됩니다. 그게 realWorldPoint가 되는 것이죠. 

 자 그럼 이제 본격적으로 Kinect Orbit을 사용해서 만들어보겠습니다. 우선 라이브러리와 Kinect와 KinectOrbit을 쓰기위한 변수를 선언해줘야 합니다. 우선 3차원상의 물체를 표현하는 것이므로 내장된 opengl 라이브러리가 필요합니다.



그다음 채울 것은 이 스크린을 구성할 setup을 지정해줘야 하는 것이죠. 역시 다음과 같이 해줍니다. 



참고로 Depth를 이용해야 하기 때문에 Depth 기능을 활성화 시키는 코드가 setup에 들어가야 하겠지요.

이제 채울 것은 draw인데요. 여기서 새롭게 사용되는 SimpleOpenNI 메서드가 drawCamFrustum() 이라는 것이 있습니다. 그래픽스 처리하시는 분이라면 프러스텀이라는 용어가 새롭지 않을겁니다. 이 메서드는 기존의 KinectOrbit이 하던 3차원 공간에서 Cam의 위치를 지정하고 기준을 지정하는 역할을 합니다. 그냥 간단하게 말하자면 3차원상에서 키넥트의 위치를 그리고 보여줍니다. 그걸로써 사용자가 키넥트로부터 얼마나 떨어져 있는지 위치를 가늠할 수 있게 하는 것이지요. 앞에서 다뤘던 DepthMap3D에서도 마지막 부분에 그게 쓰였습니다. 우선 draw 부분을 다음과 같이 채워줍니다.



지난 포스트를 복습하자면 KinectOrbit에서도 앞에서 다뤘던 3차원 Matrix와 마찬가지로 Push와 Pop의 묶음 형태로 이뤄집니다. 그래서 그 안에 자신이 원하는 코드를 삽입하면 위에서 선언한 KinectOrbit의 공간속에 구현이 됩니다. 


 자 이제 drawPointCloud라는 메서드를 만들었으니까 이걸 정의해줘야 합니다. 사실 이부분은 앞의 DepthMap3D와 많이 유사합니다.



기존에도 한번 나왔었지만 PVector를 설명하자면 그냥 프로세싱에서 다루는 Vector 클래스입니다. 한포인트에 관한 3차원 정보가 이 안에 담기는 겁니다. 여러분들이 알고있는 수학의 정도라면 3차원 정보가 나왔을때 그에 대한 위치나 gradient, magnitude 같은 걸 구하실 수 있겠지요. 당연히 벡터니까 외적이나 내적같은 개념도 동시에 적용할 수 있겠고요.

자 그럼 예제를 조금만 형을 바꿔서 그대로 집어넣어봅시다.



참고로 step의 크기를 줄이거나 늘리거나 해보세요. 역시 결과를 확인해보면 다음과 같습니다.



참고로 조금 색깔 구분이 안간다라고 하시는 분은 해당 코드를 삽입해보시기 바랍니다.



역할은 기존에 말씀드린것처럼 depthMap을 통해서 각 픽셀에 대한 정보를 얻어올 수 있습니다. 그래서 각각의 x와 y값을 통한 depthMap의 색깔을 바꾸는 겁니다. 


맨처음 예제보다는 정확하지는 않지만 그나마 depthMap을 통해서 PointCloud를 구현해볼 수 있었습니다. 

어떤가요? 지금 여러분이 구현한 코드는 단 50줄도 안되는 짧은 줄입니다. 그에 비해서 우리가 보는 것들은 기존에 보지 못한 신기한 것들입니다. 더욱더 공부를 하고 구현한다면 더 신기한 것도 만들어 낼 수 있겠지요.


사실 위의 코드를 한방에 줄이는 코드를 언급하면


위와 같이 작성하면 앞에 나온 코드와 비슷한 결과가 나옵니다. 차이가 있다면 앞의 코드는 1차원 배열에서 index를 옮기면서 depthValue를 읽는 반면 뒤에 나온 코드는 2차원 배열입니다. 물론 결과는 똑같습니다만 조금 처리하는데 있어서 기존 것보다 속도가 조금 느리게 느껴집니다. 물로 코드자체가 간단해지니까 이걸 써먹어도 상관은 없을겁니다. 


마지막으로 이렇게 만든 depthMap에 Color를 입히는 작업을 해봅시다. 우선은 2차원 배열방법이 아닌 기존 방법에서 수정을 해보겠습니다. 우선은 색상을 사용할 예정이니 setup에서 색상부분을 활성화시킵니다. 그리고 추가적으로 활성화시키는 것이 있습니다.

바로 alternativeViewPointDepthToImage라는 건데 이걸 사용하면 픽셀에 따른 Depth와 Color를 매핑해주는 함수입니다. 이걸 활용하면 회색만 나오던 게 Color값으로 변해서 나옵니다. 마지막으로 한가지 더 수정해야 될 부분이 있습니다.

기존에는 픽셀 값에서 depthValue를 Stroke시키는 부분이 있었는데요. 그 부분을 다음과 같이 수정해줍니다.



기존에 회색만 나오던게 stroke때문이었는데 이 값을 pixel값으로 바꿔주는 것입니다. 앞에서 활성화시킨 alternativeViewPointDepthToImage를 써야 이렇게 활용하는게 가능합니다. 수정하고 결과를 확인해보겠습니다.



조금 희미하긴 한데 그래도 어느정도 색상이 나오는 걸 보실 수 있습니다. 예제중에도 이런 예제가 있습니다. 거기서는 조금더 명확하게 나옵니다. 



제가 생각하긴 따로 Color에 Weight를 준거 같은데 이유는 잘 모르겠네요. 아무튼 한번쯤 해보면 신기한 프로젝트입니다. 이에 대한 프로젝트도 드롭박스를 통해서 제공됩니다.

https://dl.dropbox.com/u/96808368/processing/KinectSpace.zip

댓글