zoukankan      html  css  js  c++  java
  • 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 }

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

        最后的效果如下图:

        

        

  • 相关阅读:
    『Power AI by AI』 PAI-AutoML2.0重磅发布
    基于 K8s 做应用发布的工具那么多, 阿里为啥选择灰姑娘般的 Tekton ?
    编码方法论,赋能你我他
    开发部署效率提升 12 倍,这款应用托管服务让云上运维更简单
    全景还原报错现场 | 应用实时监控 ARMS 上线用户行为回溯功能
    告别诊断烦恼 | 应用实时监控 ARMS 上线智能和实时诊断功能
    阿里云CDN上线 WAF,一站式提供分发+安全能力
    RDS for PostgreSQL 云盘加密功能使用方法
    MySQL8.0.17
    2370 小机房的树
  • 原文地址:https://www.cnblogs.com/tszhao/p/3103401.html
Copyright © 2011-2022 走看看