zoukankan      html  css  js  c++  java
  • Kinect+OpenNI学习笔记之4(OpenNI获取的图像结合OpenCV显示)

      前言

      本文来结合下opencv的highgui功能显示kinect采集得来的颜色图和深度图。本来在opencv中自带了VideoCapture类的,使用该类可以直接驱动kinect设备,具体的可以参考下面的文章:http://blog.csdn.net/moc062066/article/details/6949910,也可以参考opencv提供的官方文档:http://docs.opencv.org/doc/user_guide/ug_highgui.html。这种方法用起来非常简单,不需要考虑OpenNI的驱动过程,有点像傻瓜式的操作。不过本人在使用该种方法时kinect一直驱动不成功,即使用opencv的VideoCapture类来捕捉Kinect设备的数据,一直是打不开的,即驱动不成功。但是kinect设备已经连接上了,且能运行openni中的sample,说明kinect的硬件驱动是没问题的,应该是opencv这个类的bug,网上很多人都碰到了该情况。

      所以还是使用前面2篇博文介绍的,自己用OpenNI写驱动,这样可以更深刻的对OpenNI这个库灵活运用。

      开发环境:QtCreator2.5.1+OpenNI1.5.4.0+Qt4.8.2+OpenCV2.4.2

      实验说明

      在用OpenCV显示OpenNI的数据时,先来了解下Kinect获取到的深度信息的一些特点,Heresy的文章:Kinect + OpenNI 的深度值 介绍得比较通俗易懂。下面是个人觉得kinect深度信息比较重要的地方:Kinect官方推荐的使用距离为1.2m到3.6m之间。其中1.2m时的精度为3mm,3.2米的时候精度越为3cm。随着距离越来越远,其检测到的精度也越来越小。精度最小为1mm,大概是距离50cm时,不过此时的点数量比较少,也不稳定,因此官方没有推荐使用这个时候的距离。

      另外还需要注意OpenNI中表示深度像素的格式为XnDepthPixel,实际上是单一channel的16位正整数,因此如果使用OpenCV来存储时,需要设定格式为CV_16UC1。因此其范围是0~65536,不过期最大的深度只能感应到10000,所以我们需要将其归一化到一个比较好的范围内。

      本文使用的是上一篇博文:Kinect+OpenNI学习笔记之3(获取kinect的数据并在Qt中显示的类的设计) 中用到的类COpenNI,该类可以方便的驱动kinect,并将获得的色彩信息和深度信息保存在共有变量中,提供其对象来调用。主函数中使用OpenCV库来创建窗口,且将Kinect获到的数据转换成OpenCV的格式,然后在创建的窗口中显示。同时也对深度图像和颜色图像进行了canny边缘检测并显示出来比较。

      实验结果

      本实验显示4幅图像,分别为颜色原图及其canny边缘检测图,深度原图及其canny边缘检测图。结果截图部分图如下:

      实验主要部分代码及注释(附录有实验工程code下载链接地址):

    copenni.cpp:

    #include <XnCppWrapper.h>
    #include <QtGui/QtGui>
    #include <iostream>
    
    using namespace xn;
    using namespace std;
    
    class COpenNI
    {
    public:
        ~COpenNI() {
            context.Release();//释放空间
        }
        bool Initial() {
            //初始化
            status = context.Init();
            if(CheckError("Context initial failed!")) {
                return false;
            }
            context.SetGlobalMirror(true);//设置镜像
            //产生图片node
            status = image_generator.Create(context);
            if(CheckError("Create image generator  error!")) {
                return false;
            }
            //产生深度node
            status = depth_generator.Create(context);
            if(CheckError("Create depth generator  error!")) {
                return false;
            }
            //视角校正
            status = depth_generator.GetAlternativeViewPointCap().SetViewPoint(image_generator);
            if(CheckError("Can't set the alternative view point on depth generator")) {
                return false;
            }
    
            return true;
    
        }
    
        bool Start() {
            status = context.StartGeneratingAll();
            if(CheckError("Start generating error!")) {
                return false;
            }
            return true;
        }
    
        bool UpdateData() {
            status = context.WaitNoneUpdateAll();
            if(CheckError("Update date error!")) {
                return false;
            }
            //获取数据
            image_generator.GetMetaData(image_metadata);
            depth_generator.GetMetaData(depth_metadata);
    
            return true;
        }
    
    public:
        DepthMetaData depth_metadata;
        ImageMetaData image_metadata;
    
    private:
        //该函数返回真代表出现了错误,返回假代表正确
        bool CheckError(const char* error) {
            if(status != XN_STATUS_OK ) {
                QMessageBox::critical(NULL, error, xnGetStatusString(status));
                cerr << error << ": " << xnGetStatusString( status ) << endl;
                return true;
            }
            return false;
        }
    
    private:
        XnStatus    status;
        Context     context;
        DepthGenerator  depth_generator;
        ImageGenerator  image_generator;
    };

    main.cpp:

    #include <QCoreApplication>
    
    #include "opencv2/highgui/highgui.hpp"
    #include "opencv2/imgproc/imgproc.hpp"
    #include <opencv2/core/core.hpp>
    #include "copenni.cpp"
    
    #include <iostream>
    
    using namespace cv;
    using namespace xn;
    
    int main (int argc, char **argv)
    {
        COpenNI openni;
        if(!openni.Initial())
            return 1;
    
        namedWindow("color image", CV_WINDOW_AUTOSIZE);
        namedWindow("color edge detect", CV_WINDOW_AUTOSIZE);
        namedWindow("depth image", CV_WINDOW_AUTOSIZE);
        namedWindow("depth edge detect", CV_WINDOW_AUTOSIZE);
    
        if(!openni.Start())
            return 1;
        while(1) {
            if(!openni.UpdateData()) {
                return 1;
            }
            /*获取并显示色彩图像*/
            Mat color_image_src(openni.image_metadata.YRes(), openni.image_metadata.XRes(),
                                CV_8UC3, (char *)openni.image_metadata.Data());
            Mat color_image;
            cvtColor(color_image_src, color_image, CV_RGB2BGR);
            imshow("color image", color_image);
    
            /*对色彩图像进行canny边缘检测并显示*/
            Mat color_image_gray, color_image_edge;
            cvtColor(color_image_src, color_image_gray, CV_RGB2GRAY);//因为在进行边缘检测的时候只能使用灰度图像
            Canny(color_image_gray, color_image_edge, 5, 100);
            imshow("color edge detect", color_image_edge);
    
            /*获取并显示深度图像*/
            Mat depth_image_src(openni.depth_metadata.YRes(), openni.depth_metadata.XRes(),
                                CV_16UC1, (char *)openni.depth_metadata.Data());//因为kinect获取到的深度图像实际上是无符号的16位数据
            Mat depth_image, depth_image_edge;
            depth_image_src.convertTo(depth_image, CV_8U, 255.0/8000);
            imshow("depth image", depth_image);
    
            /*计算深度图像的canny边缘并显示*/
            Canny(depth_image, depth_image_edge, 5, 100);
            imshow("depth edge detect", depth_image_edge);
            waitKey(30);
    
        }
    
    }

      总结:本实验将OpenNI驱动的Kinect数据转换成OpenCV中方便处理的格式,达到了将OpenNI和OpenCV两者相结合的目的。

      参考资料:

         Kinect+OpenNI学习笔记之3(获取kinect的数据并在Qt中显示的类的设计)

         opencv2.3读取kinect深度信息和彩色图像

         Kinect + OpenNI 的深度值

         OpenNI + OpenCV

      附录: 实验工程code下载

  • 相关阅读:
    简明Python3教程 12.问题解决
    简明Python3教程 11.数据结构
    【SPOJ 694】Distinct Substrings
    【codeforces Manthan, Codefest 17 C】Helga Hufflepuff's Cup
    【CF Manthan, Codefest 17 B】Marvolo Gaunt's Ring
    【CF Manthan, Codefest 17 A】Tom Riddle's Diary
    【SPOJ 220】 PHRASES
    【POJ 3261】Milk Patterns
    【POJ 3294】Life Forms
    【POJ 1226】Substrings
  • 原文地址:https://www.cnblogs.com/tornadomeet/p/2709851.html
Copyright © 2011-2022 走看看