Intel RealSense 카메라의 HandDetect 기능을 테스트 해 봤습니다.

 

한손으로 손을 쥐었을때 3D Model 을 회전 시키고,

 

양손일때는 손을 쥐었을때는 깊이를 감지해 3D 모델을 밀거나 당기는 예제를 만들어 봤습니다.

 

 

동작 방식을 테스트 하기 위해 다양한 모드를 넣었는데요. 


스켈리톤 모드에서 Label 체크를 하지 않았을때는 Depth 맵 전체가 나옵니다.

Label 체크를 했을때는 손만 나오게 됩니다. 


커서 모드에서 Depth 라벨을 체크하지 않았다면 손을 쥐었을대 3D 모델을 회전시킵니다.

Depth 라벨을 체크 했다면 손을 폈을때 회전 시키고 손을 쥐었을때 손의 깊이에 따라 3D 모델을 당기거나 미는 효과를 줍니다. 


Kinect 보다 섬세하고 자연스러운 컨트롤이 가능합니다.

 

다만 20cm 에서 150m 정도의 깊이만 감지 할 수 있다는점과, 


보다 먼 거리에서는 얼굴, 손, 등의 인식도 잘 안된다는것이 아쉽습니다.


테스트 결과 1.5m ~ 3 m 까지는 불안정하지만 얼굴이나 손은 인식 했던것 같습니다. 

 

보다 먼 거리를 테스트 할 수 있는 RealSense 시리즈 기기도 있지만 수중에 재고가 없어 테스트 해보지는 못했습니다.

 

 

왼손인지 오른손인지, 손을 쥐었는지 폈는지, 몇번째 손가락인지 등등의 자세한 내용 까지고 감지가 가능했습니다.

 

깊이 지각 기능을 더하면 동영상과 같은 재미있는 인터렉션이 가능합니다. 간단한 게임 정도는 금방 만들겠네요.


git: https://github.com/acidkay9731/BLOG_RS_HandTracking

 

 

 

 

 

 

키넥트의 Depth Map 은 명암으로 제공됩니다.

 

실제 사진상 위치의 거리를 알고 싶어 예제를 수정해 봤습니다.

 

마우스를 클릭 한 곳의 거리를 메세지박스로 보여줍니다.

 

 

실행 화면:

 

 

 

중요 코드는 다음과 같습니다.

 

 

1. depthPixels 변수 아래 실제 거리가 들어갈 변수를 선언해 줍니다.

1
2
3
4
5
/// <summary>
/// Intermediate storage for frame data converted to color
/// </summary>
private byte[] depthPixels = null;
private int[] realDepthPixels = null;
cs

 

 

2. MainWindows() 에서 초기화 해 줍니다.

1
2
3
4
5
6
7
8
9
/// <summary>
/// Initializes a new instance of the MainWindow class.
/// </summary>
public MainWindow()
{
    // allocate space to put the pixels being received and converted
    this.depthPixels = new byte[this.depthFrameDescription.Width * this.depthFrameDescription.Height];
    this.realDepthPixels = new int[this.depthFrameDescription.Width * this.depthFrameDescription.Height];
}
cs

 

 

3. ProcessDepthFrameData 함수에 다음과 같이 한 줄을 추가해 줍니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
private unsafe void ProcessDepthFrameData(IntPtr depthFrameData, uint depthFrameDataSize, ushort minDepth, ushort maxDepth)
{
    // depth frame data is a 16 bit value
    ushort* frameData = (ushort*)depthFrameData;
 
    // convert depth to a visual representation
    for (int i = 0; i < (int)(depthFrameDataSize / this.depthFrameDescription.BytesPerPixel); ++i)
    {
        // Get the depth for this pixel
        ushort depth = frameData[i];
 
        // To convert to a byte, we're mapping the depth value to the byte range.
        // Values outside the reliable depth range are mapped to 0 (black).
        this.depthPixels[i] = (byte)(depth >= minDepth && depth <= maxDepth ? (depth / MapDepthToByte) : 0);
        // added line
        this.realDepthPixels[i] = (int)(depth >= minDepth && depth <= maxDepth ? (depth) : 0);
    }
}
cs

 

 

4. 클릭을 하면 거리를 보여주는 이벤트 함수를 추가합니다.

1
2
3
4
5
6
7
8
private void imgDepth_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
    Point point = e.GetPosition(imgDepth);
 
    int distance = realDepthPixels[((int)point.Y) * this.depthBitmap.PixelWidth + ((int)point.X)];
 
    MessageBox.Show(distance + "cm""Distance of Cursor");
}
cs

 

 

 

 

ps. Depth Map 이 아닌 실제 이미지에서 Depth Map 의 거리값을 알고 싶을경우 다음과 같이 비율로 변환하여 값을 얻어시면 됩니다.

1
2
3
4
5
6
7
8
9
10
11
private void imgColor_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
    Point p = e.GetPosition(imgColor);
 
    cvtPixelToDepthX = Convert.ToInt32((depthBitmap.PixelWidth * p.X) / this.displayWidth);
    cvtPixelToDepthY = Convert.ToInt32((depthBitmap.PixelHeight * p.Y) / this.displayHeight);
 
    int tmpFaceCenterDistance = realDepthPixels[cvtPixelToDepthY * this.depthBitmap.PixelWidth + cvtPixelToDepthX];
 
    MessageBox.Show(tmpFaceCenterDistance + "cm");
}
cs

 

 

 

 

'DEVELOP > Image Processing' 카테고리의 다른 글

Intel RealSense Camera HandDetect Example  (0) 2017.03.07
OpenCV 3.1 개발환경 셋팅 (CPP, MFC)  (0) 2016.08.30

 

 

환경: OpenCV 3.1, Visual Studio 2015, 2013

 

※ OpenCV 는 c:\Opencv_3.1 에 설치되어 있는걸로 가정합니다.

 

 

1. 프로젝트에서 마우스 우클릭 -> 속성

 

 

 

2. 구성에서 32bit, x86 관련 설정을 지워야 합니다. 플랫폼 콤보 박스를 선택합니다.

※ OpenCV 3.1 은 32bit dll 이 없습니다. 소스를 가지고 직접 컴파일 하면 가능하다고 알고있는데, 확실하진 않습니다.

 

 

3. 편집 메뉴 클릭

 

 

 

4. x86을 선택하고 제거 버튼을 클릭합니다.

 

 

 

5. [활성 솔루션 플랫폼] 콤보박스 아래 [플랫폼] 콤보박스를 클릭하여 [편집] 메뉴를 클릭합니다.

 

 

 

6. Win32 를 선택 후 제거 버튼을 클릭합니다.

 

 

 

7. 닫기 버튼을 클릭하여 구성관리자를 닫습니다.

 

 

 

7.5. [구성] 콤보 박스를 [모든 구성] 으로 변경합니다.

     Debug 로 둔 채로 수정하면 Release 로 변경 후 한번 더 설정해야 합니다.

 

8. 왼쪽 구성 트리에서 [C/C++] 노드를 선택하고 디렉터리 콤보박스의 편집 메뉴를 클릭합니다.

 

 

 

9. 줄 추가 버튼을 클릭 한 후 새로 생긴 줄(2번) 의 오른쪽 끝 ... 버튼을 클릭합니다.

 

 

 

10. C:\opencv_3.1\build\include 경로를 찾아가 폴더선택 버튼을 클릭합니다.

 

 

 

11. 계속해서 하위 디렉터리인 C:\opencv_3.1\build\include\opencv 와 C:\opencv_3.1\build\include\opencv2 경로를 추가합니다.

 

 

 

12. 왼쪽 트리 메뉴에서 링커 노드를 선택 후 추가 라이브러리 디렉터리 콤보박스에서 편집 메뉴를 클릭합니다.

 

 

 

13. C:\opencv_3.1\build\x64\vc14\lib 경로를 찾아가 폴더 선택 버튼을 클릭합니다.

※ Visual Studio 2013 일 경우 C:\opencv_3.1\build\x64\vc12\lib 경로를 선택합니다.

 

 

 

14. 구성 콤보박스를 Debug 로 변경합니다.

 

 

 

15. 지금까지 설정한 내용을 저장하겠냐고 물어봅니다. 예(Y) 버튼을 클릭합니다.

 

 

 

16. 왼쪽 트리 메뉴에서 입력 노드를 선택 후 추가 종속성 콤보박스를 클릭 후 편집 메뉴를 클릭합니다.

 

 

 

17. opencv_world310d.lib 를 클릭 후 확인 버튼을 클릭합니다. (디버그에 경우에는 이름 마지막에 d가 붙은 lib 를 참조합니다.)

 

 

 

18. 구성 콤보 박스를 Release 로 변경합니다. 위와 같이 저장 하겠냐는 메세지가 나오면 예(Y) 버튼을 클릭합니다.

 

 

 

19. opencv_world310.lib (이번엔 이름 마지막에 d가 없습니다.) 을 입력하고 확인 버튼을 클릭합니다.

 

 

 

20. stdafx.h 헤더에 다음과 같은 구문을 추가합니다.

#include "opencv2\opencv.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"

using namespace cv;
using namespace std;

 

 

 

정상적으로 컴파일이 된다면 구성 완료입니다.

 

+ Recent posts