Kinect+OpenNI学习笔记之4(OpenNI获取的图像结合OpenCV显示)
来源:互联网 发布:为啥淘宝提交不了订单 编辑:程序博客网 时间:2024/04/28 19:44
转载地址:http://www.cnblogs.com/tornadomeet/archive/2012/10/01/2709851.html
前言
本文来结合下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下载。
- Kinect+OpenNI学习笔记之4(OpenNI获取的图像结合OpenCV显示)
- OpenNI结合OpenCV显示Kinect彩色、深度及融合图像
- kinect,openni,opencv 获取并显示深度与彩色图像
- 使用opencv显示openni获取的图像
- Kinect+OpenNI学习笔记之3(获取kinect的数据并在Qt中显示的类的设计)
- OpenNI学习笔记1-获取kinect的颜色图像和深度图像
- kinect+openni获取kinect的颜色图像和深度图像
- Kinect+OpenNI学习笔记之5(使用OpenNI自带的类进行简单手势识别)
- Kinect+OpenNI学习笔记之1(开发环境的建立)
- OPENNI学习实践-利用opencv显示图像
- (转)Kinect+OpenNI学习笔记
- Processing 结合OpenNI开发kinect的简单笔记
- Kinect+OpenNI+OpenCV+VS2010
- Kinect+OpenNI+OpenCV使用
- OPENNI学习实践-openni+kinect 获取真实世界坐标
- Opencv及Kinect/OpenNI常用学习网址
- Opencv及Kinect/OpenNI常用学习网址
- Opencv及Kinect/OpenNI常用学习网址
- php平均分配算法
- iOS手机号段的正则匹配(包含最新号段)
- Android之ADB详解
- 广告墙、推送广告、广告条
- 第十四周上机实践项目——动物这样叫(抽象类法)
- Kinect+OpenNI学习笔记之4(OpenNI获取的图像结合OpenCV显示)
- 第14周-项目2-形状类族中的纯虚构函数
- IOS自动化打包介绍
- poj1860
- 最小生成树
- 《C/C++代码优化的27个建议》
- hover 在 ie 中使用失效问题
- 经典C 1-10
- display:none与visible:hidden的区别