Kinect开发(2)-景深数据获取

    上一节讲了OpenNI2开发Kinect的基本框架,但是,具体的数据流获取并没有详细介绍,本篇文章开始介绍数据流的获取与处理。采用OpenCV进行图像的处理与显示。

    获取景深数据有2种方式,一种是轮询,另外一种是设置一个Listener,当有新的数据帧到达时,会通知该Listener。下面分别实现这两种方式。    

    先上代码,注:为了更清晰的展示主要过程,对于一些错误及异常都没有进行判断,代码写的比较简陋。

    方式一:轮询

 1 #include <iostream>
 2 using namespace std;
 3 
 4 #include <OpenNI.h>
 5 #pragma comment(lib, "openni2.lib")
 6 
 7 #include <opencv/cv.h>
 8 #include <opencv/highgui.h>
 9 #pragma comment(lib, "opencv_core244.lib")
10 #pragma comment(lib, "opencv_highgui244.lib")
11 
12 int main()
13 {
14     openni::Status rc = openni::STATUS_OK;
15     openni::Device device;
16     openni::VideoStream depthStream;
17     openni::VideoFrameRef frame;
18     IplImage* img = NULL;
19     char* pImgData = NULL;
20     //初始化设备驱动
21     openni::OpenNI::initialize();
22     //打开设备
23     device.open(openni::ANY_DEVICE);
24     //接收景深传感器的数据
25     depthStream.create(device, openni::SENSOR_DEPTH);
26     depthStream.start();
27     cvNamedWindow("wnd", CV_WINDOW_AUTOSIZE);
28     while (true)
29     {
30         depthStream.readFrame(&frame);
31         if (frame.isValid())
32         {
33             openni::DepthPixel* pData = (openni::DepthPixel*)frame.getData();
34             if (!pImgData)
35             {
36                 pImgData = new char[frame.getHeight()*frame.getWidth()];
37             }
38             if (!img)
39             {
40                 img = cvCreateImage(cvSize(frame.getWidth(), frame.getHeight()),8, 1);
41             }
42             for (int row=0; row!=frame.getHeight(); ++row)
43             {
44                 for (int col=0; col!=frame.getWidth(); ++col)
45                 {
46                     pImgData[row*frame.getWidth() + col] = (char)pData[row*frame.getWidth()+col]%256;
47                 }
48             }
49             img->imageData = pImgData;
50             cvShowImage("wnd", img);
51             char c = cvWaitKey(30);
52             if (c == 27)
53             {
54                 cvReleaseImage(&img);
55                 delete[] pImgData;
56                 cvDestroyWindow("wnd");
57                 break;
58             }
59         }
60     }
61     depthStream.stop();
62     depthStream.destroy();
63     device.close();
64     openni::OpenNI::shutdown();
65     return 0;
66 }

    首先进行驱动、设备的初始化,由于上一节中已经介绍过,不再进行赘述。

    27:初始化一个OpenCV的窗口,用于显示处理之后的深度数据。

    30:从VideoStream中读取景深数据的数据帧。数据帧是openni::VideoFrameRef类型,该对象保存着本帧数据的宽高、时间戳、帧计数等信息。

    31:判断该数据帧是否有效。

    33:获取到该帧的数据,注意,OpenNI是用2个字节来表示一个景深数据,也就是DepthPixel其实就是uint16_t类型。

    34-41:根据该帧的信息,分配OpenCV需要用到的结构。

    42-48:这里只是进行一个简单的处理,对每个深度数据取256的模,以便进行区分。

    49-50:把处理后的数据在窗口中显示出来。

    方式二:事件

 1 #include <conio.h>
 2 #include <iostream>
 3 using namespace std;
 4 
 5 #include <OpenNI.h>
 6 #pragma comment(lib, "openni2.lib")
 7 
 8 #include <opencv/cv.h>
 9 #include <opencv/highgui.h>
10 #pragma comment(lib, "opencv_core244.lib")
11 #pragma comment(lib, "opencv_highgui244.lib")
12 
13 class NewDepthFrameListener
14     : public openni::VideoStream::NewFrameListener
15 {
16 public:
17     NewDepthFrameListener():m_pImg(nullptr), m_pImgData(nullptr) {};
18     ~NewDepthFrameListener()
19     {
20         if (m_pImg)
21         {
22             cvReleaseImage(&m_pImg);
23             m_pImg = nullptr;
24         }
25         if (m_pImgData)
26         {
27             delete[] m_pImgData;
28             m_pImgData = nullptr;
29         }
30     }
31 
32 public:
33     virtual void onNewFrame(openni::VideoStream& stream)
34     {
35         openni::VideoFrameRef frame;
36         stream.readFrame(&frame);
37         if (frame.isValid())
38         {
39             const openni::DepthPixel* pData = (openni::DepthPixel*)frame.getData();
40             if (!m_pImgData)
41             {
42                 m_pImgData = new char[frame.getWidth()*frame.getHeight()];
43             }
44             if (!m_pImg)
45             {
46                 m_pImg = cvCreateImage(cvSize(frame.getWidth(), frame.getHeight()), 8, 1);
47             }
48             for (int row=0; row!=frame.getHeight(); ++row)
49             {
50                 for (int col=0; col!=frame.getWidth(); ++col)
51                 {
52                     m_pImgData[row*frame.getWidth() + col] = (char)pData[row*frame.getWidth()+col]%256;
53                 }
54             }
55             m_pImg->imageData = m_pImgData;
56             cvShowImage("wnd", m_pImg);
57             frame.release();
58         }
59     }
60 
61 private:
62     char* m_pImgData;
63     IplImage* m_pImg;
64 };
65 
66 int main()
67 {
68     openni::Status rc = openni::STATUS_OK;
69     openni::Device device;
70     openni::VideoStream depthStream;
71     openni::VideoFrameRef frame;
72     NewDepthFrameListener listener;
73     IplImage* img = NULL;
74     char* pImgData = NULL;
75     //初始化设备驱动
76     openni::OpenNI::initialize();
77     //打开设备
78     device.open(openni::ANY_DEVICE);
79     //接收景深传感器的数据
80     depthStream.create(device, openni::SENSOR_DEPTH);
81     depthStream.start();
82     depthStream.addNewFrameListener(&listener);
83     cvNamedWindow("wnd", CV_WINDOW_AUTOSIZE);
84     while (true)
85     {
86         if (cvWaitKey(30) == 27)
87         {
88             break;
89         }
90     }
91     cvDestroyWindow("wnd");
92     depthStream.stop();
93     depthStream.destroy();
94     device.close();
95     openni::OpenNI::shutdown();
96     return 0;
97 }

    代码比较简单,就不再进行说明。

    最后的效果如下图:

    

    

posted @ 2013-05-28 16:05  tszhao  阅读(945)  评论(0编辑  收藏  举报