**PCD数据获取:Kinect+OpenNI+PCL对接(代码)
前言:
PCL使用点云作为数据格式,Kinect可以直接作为三维图像的数据源产生三维数据,其中的桥梁是OpenNI和PrimeSense。为了方便地使用Kinect的数据,还是把OpenNI获取的基础数据格式转换为点云格式。并且PCD格式的数据操作起来更为直观。
切记:理论自己慢慢看,代码是最重要的,且测试可行且正确
(1):Microsoft Kinect SDK 和 PrimeSense OpenNI 的区别
原文链接:http://blog.csdn.net/wdxzkp/article/details/6608817
注解:作者写了一系列博文,可以借鉴一下:
After playing with both the Microsoft Kinect SDK and
the PrimeSense OpenNI SDK here are some of my thoughts,Note that the Microsoft’s SDK version is the Beta version, so things may change when the final one is released)
Kinect SDK (Beta)pro: 优点
- support for audio 支持音频
- support for motor/tilt 支持马达
- full body tracking: 全身追踪
- does
not need a calibration pose 不需要标定姿势(投降姿势) - includes
head, hands, feet, clavicles 包括头,手,脚和锁骨 - seems
to deal better with occluded joints 看起来处理关节闭塞更好些
- does
- supports multiple sensors 支持多传感器(多台Kinect)
- single no-fuss installer 简化安装(安装更容易)
- SDK has events for when a new Video or new Depth frame is available 当新的视频或深度图有效时,SDK会有可用事件
con: 缺点
- licensed for non-commercial use only 非商用(商业需要付费)
- only tracks full body (no mode for hand only tracking) 只能追踪全身(不包含特定的追踪模式:例如只追踪手)
- does not offer alignment of the color&depth image streams to one
another yet
although there are features to align individual coordinates - and there are hints that support may come later
full body tracking: 全身追踪
only
calculates positions for the joints, not rotations 关节只有坐标数据,没有旋转数据 only
tracks the full body, no upperbody or hands only mode 只能追踪全身,不包含特定的追踪模式:例如只追踪手或上半身
seems
to consume more CPU power than OpenNI/NITE (not properly benchmarked) 和OpenNI/NITE相比,看起来更消耗CPU(没有采用适当的基准)
no gesture recognition system 不包含手势识别系统 no
support for the PrimeSense and the ASUS WAVI Xtion sensors? (can anyone confirm this?) 不支持PrimeSense和华硕的WAVI
Xtion硬件平台 only supports Win7 (x86 & x64) 只支持Win7(32位和64位) no
support for Unity3D game engine 不支持Unity3D游戏引擎 no
built in support for record/playback to disk 不支持数据记录或回放到硬盘 no
support to stream the raw InfraRed video data 不支持红外线视频数据流
SDK does not have events for when new user enters frame, leaves
frame etc SDK没有此类发生事件,例如当一个用户被侦测到或用户丢失等等。
PrimeSense OpenNI/NITEpro: 优点
- license includes commercial use 可以商用(不需要付费)
- includes a framework for hand tracking 包含手部追踪框架
- includes a framework for hand gesture recognition 包含手势识别框架
- can automatically align the depth image stream to the color image 可以自动对齐深度图数据到彩色图数据
- full body tracking: 全身追踪
- also
calculates rotations for the joints 包含坐标数据和旋转数据 - support
for hands only mode 支持特殊跟踪模式:例如:只追踪手和头或上半身 - seems
to consume less CPU power than Microsoft Kinect SDK’s tracker (not properly benchmarked) 和微软的SDK相比消耗的CPU更少
- also
- also supports the Primesense and the ASUS WAVI Xtion sensors 支持Primesense和华硕的WAVI
Xtion硬件平台 - supports multiple sensors although setup and enumeration is a
bit quirky 支持多传感器但是需要安装和枚举,这一点有点古怪。 - supports Windows (including Vista&XP), Linux and Mac OSX 支持Windows(包括Vista&XP&WIN7),Linux系统和苹果操作系统(翻者:也支持Android)
- comes with code for full support in Unity3D game engine 自带的代码全面支持Unity3D游戏引擎(翻者:也支持Ogre)
- support for record/playback to/from disk 支持数据记录到硬盘或从硬盘回放数据
- support to stream the raw InfraRed video data 支持红外数据流
- SDK has events for when new User enters frame, leaves frame etc SDK有此类发生事件,例如:当一个用户被侦测到或者用户丢失。(提供回调函数供开发者使用)
con: 缺点
- no support for audio 不支持音频
- no support for motor/tilt (although you can simultaneously use
the CL-NUI motor drivers) 不支持马达(翻者:马达是微软的专利,所以primesense公司不想惹微软) - full body tracking: 全身追踪
- lacks
rotations for the head, hands, feet, clavicles 缺乏以下关节:头,手,脚,和锁骨 - needs
a calibration pose to start tracking (although it can be saved/loaded to/from disk for reuse) 需要一个标定姿势(投降姿势)才能开始追踪骨骼(注意:标定数据是可以存储和提取的方便重用) - occluded
joints are not estimated 关节闭塞没有被估算
- lacks
- supports multiple sensors although setup and enumeration is a
bit quirky 支持多感应器但是需要安装和枚举,这一点有点古怪。 - three separate installers and a NITE license string (although
the process can be automated with my auto driver installer) 需要单独安装NITE - SDK does not have events for when new Video or new Depth frames
is available SDK没有此类发生事件,例如:当新的视频或者深度图数据有效时。(翻者:OpenNI提供了类似功能的函数可使用,虽然不是回调函数,但是也很好用)
(Personal) conclusion:Microsoft
seems to have the edge when working with skeletons and/or audio.
微软在骨骼识别和音频方面有优势。(翻者:本人非常认同,微软的音频识别将会在未来的体感游戏里发挥重要的作用!)
OpenNI seems
to be best suited when working on colored pointclouds, on non-Win7 platforms and/or for commercial projects.
OpenNI似乎更适合做一些带颜色的点云的工作,和在非Win7平台来开发商业项目。
When working with gestures in specific: 手势识别
- If your sensor only sees the upperbody/hands and/or you want an
existing framework to start with use OpenNI/NITE.
如果你想开发基于上半身或手识别的项目,可以使用OpenNI和NITE - When your sensor can see the full body the more stable Microsoft
skeleton may be the best to use, however you’ll have to code your own gesture recognitions. (You’d also have to extend OpenNI/NITE for fullbody gestures btw)
全身识别毋庸置疑微软的SDK是最好的,然而你必须自己编写你自己的手势识别代码。
(2):数据获取借鉴的三篇文章:
透過 OpneNI 讀取 Kinect 深度影像資料
:http://viml.nchc.org.tw/blog/paper_info.php?CLASS_ID=1&SUB_ID=1&PAPER_ID=215
透過 OpneNI 合併 Kinect 深度以及彩色影像資料
http://viml.nchc.org.tw/blog/paper_info.php?CLASS_ID=1&SUB_ID=1&PAPER_ID=216
透過 OpenNI 建立 Kinect 3D Point Cloud:
http://viml.nchc.org.tw/blog/paper_info.php?CLASS_ID=1&SUB_ID=1&PAPER_ID=217
Kinect运用OpenNI产生点云
原文链接:http://blog.csdn.net/opensource07/article/details/7804246
(1):作者的例程:利用OpenNI读取Kinect...
#include <stdlib.h>
#include <iostream>
#include <string> #include <XnCppWrapper.h> using namespace std; void CheckOpenNIError( XnStatus eResult, string sStatus )
{
if( eResult != XN_STATUS_OK )
cerr << sStatus << " Error: " << xnGetStatusString( eResult ) << endl;
} int main( int argc, char** argv )
{
XnStatus eResult = XN_STATUS_OK; // 2. initial context
xn::Context mContext;
eResult = mContext.Init();
CheckOpenNIError( eResult, "initialize context" ); // set map mode
XnMapOutputMode mapMode;
mapMode.nXRes = 640;
mapMode.nYRes = 480;
mapMode.nFPS = 30; // 3. create depth generator
xn::DepthGenerator mDepthGenerator;
eResult = mDepthGenerator.Create( mContext );
CheckOpenNIError( eResult, "Create depth generator" );
eResult = mDepthGenerator.SetMapOutputMode( mapMode ); // 4. start generate data
eResult = mContext.StartGeneratingAll(); // 5. read data
eResult = mContext.WaitAndUpdateAll();
if( eResult == XN_STATUS_OK )
{
// 5. get the depth map
const XnDepthPixel* pDepthMap = mDepthGenerator.GetDepthMap();
// 6. Do something with depth map
}
// 7. stop
mContext.StopGeneratingAll();
mContext.Shutdown(); return 0;
}
(2):合并深度和RGB图像:基于对昌邑程序的修改。
#include <stdlib.h>
#include <iostream>
#include <string> #include <XnCppWrapper.h> using namespace std; void CheckOpenNIError( XnStatus eResult, string sStatus )
{
if( eResult != XN_STATUS_OK )
cerr << sStatus << " Error : " << xnGetStatusString( eResult ) << endl;
} int main( int argc, char** argv )
{
XnStatus eResult = XN_STATUS_OK; // 2. initial context
xn::Context mContext;
eResult = mContext.Init();
CheckOpenNIError( eResult, "initialize context" ); // 3. create depth generator
xn::DepthGenerator mDepthGenerator;
eResult = mDepthGenerator.Create( mContext );
CheckOpenNIError( eResult, "Create depth generator" ); // 4. create image generator
xn::ImageGenerator mImageGenerator;
eResult = mImageGenerator.Create( mContext );
CheckOpenNIError( eResult, "Create image generator" ); // 5. set map mode
XnMapOutputMode mapMode;
mapMode.nXRes = 640;
mapMode.nYRes = 480;
mapMode.nFPS = 30;
eResult = mDepthGenerator.SetMapOutputMode( mapMode );
eResult = mImageGenerator.SetMapOutputMode( mapMode ); // 6. correct view port
mDepthGenerator.GetAlternativeViewPointCap().SetViewPoint( mImageGenerator ); // 7. tart generate data
eResult = mContext.StartGeneratingAll(); // 8. read data
eResult = mContext.WaitNoneUpdateAll();
if( eResult == XN_STATUS_OK )
{
// 9a. get the depth map
const XnDepthPixel* pDepthMap = mDepthGenerator.GetDepthMap();
// 9b. get the image map
const XnUInt8* pImageMap = mImageGenerator.GetImageMap();
} // 10. stop
mContext.StopGeneratingAll();
mContext.Shutdown(); return 0;
}
(3):建立3D点云:对上一个程序的修改
定义一个简单的结构体:SColorPoint3D:
struct SColorPoint3D
{
float X;
float Y;
float Z;
float R;
float G;
float B; SColorPoint3D( XnPoint3D pos, XnRGB24Pixel color )
{
X = pos.X;
Y = pos.Y;
Z = pos.Z;
R = (float)color.nRed / 255;
G = (float)color.nGreen / 255;
B = (float)color.nBlue / 255;
}
};
六个点值:分別記錄這個點的位置、以及顏色;
建構子的部分:則是傳入 OpenNI 定義的結構的参数:代表位置的 XnPoint3D
以及代表 RGB 顏色的 XnRGB24Pixel。
把座標轉換的部分寫成一個函数
GeneratePointCloud(),其內容如下:
void GeneratePointCloud( xn::DepthGenerator& rDepthGen,
const XnDepthPixel* pDepth,
const XnRGB24Pixel* pImage,
vector<SColorPoint3D>& vPointCloud )
{
// 1. number of point is the number of 2D image pixel
xn::DepthMetaData mDepthMD;
rDepthGen.GetMetaData( mDepthMD );
unsigned int uPointNum = mDepthMD.FullXRes() * mDepthMD.FullYRes(); // 2. build the data structure for convert
XnPoint3D* pDepthPointSet = new XnPoint3D[ uPointNum ];
unsigned int i, j, idxShift, idx;
for( j = 0; j < mDepthMD.FullYRes(); ++j )
{
idxShift = j * mDepthMD.FullXRes();
for( i = 0; i < mDepthMD.FullXRes(); ++i )
{
idx = idxShift + i;
pDepthPointSet[idx].X = i;
pDepthPointSet[idx].Y = j;
pDepthPointSet[idx].Z = pDepth[idx];
}
} // 3. un-project points to real world
XnPoint3D* p3DPointSet = new XnPoint3D[ uPointNum ];
rDepthGen.ConvertProjectiveToRealWorld( uPointNum, pDepthPointSet, p3DPointSet );
delete[] pDepthPointSet; // 4. build point cloud
for( i = 0; i < uPointNum; ++ i )
{
// skip the depth 0 points
if( p3DPointSet[i].Z == 0 )
continue; vPointCloud.push_back( SColorPoint3D( p3DPointSet[i], pImage[i] ) );
}
delete[] p3DPointSet;
}
函数把 xn::DepthGenerator
以及讀到的深度影像和彩色影像傳進來,用來當作資料來源;
同時也傳入一個
vector<SColorPoint3D>,作為儲存轉換完成後的 3D 點位資料。
其中,深度影像的格式還是一樣用 XnDepthPixel
的 const 指標,不過在彩色影像的部分,Heresy 則是改用把 RGB 封包好的 XnRGB24Pixel,這樣可以減少一些索引值的計算;而因為這樣修改,之前讀取彩色影像的程式也要
修改為
constXnRGB24Pixel*
pImageMap = mImageGenerator.GetRGB24ImageMap();
回到主程序的部分,本來讀取資料的程序是:
// 8. read data
eResult = mContext.WaitNoneUpdateAll();
if( eResult == XN_STATUS_OK )
{
// 9a. get the depth map
const XnDepthPixel* pDepthMap = mDepthGenerator.GetDepthMap();
// 9b. get the image map
const XnUInt8* pImageMap = mImageGenerator.GetImageMap();
}
前面也提過,Heresy 這邊不打算提及用 OpenGL 顯示的部分,所以這邊為了不停地更新資料,所以改用一個無窮迴圈的形式來不停地更新資料、並進行座標轉換;
而轉換後的結果,也很簡單地只輸出它的點的數目。
修改后:
// 8. read data
vector<SColorPoint3D> vPointCloud;
while( true )
{
eResult = mContext.WaitNoneUpdateAll();
// 9a. get the depth map
const XnDepthPixel* pDepthMap = mDepthGenerator.GetDepthMap(); // 9b. get the image map
const XnRGB24Pixel* pImageMap = mImageGenerator.GetRGB24ImageMap(); // 10 generate point cloud
vPointCloud.clear();
GeneratePointCloud( mDepthGenerator, pDepthMap, pImageMap, vPointCloud );
cout << "Point number: " << vPointCloud.size() << endl;
}
如果是要用 OpenGL 畫出來的話,基本上就是不要使用無窮迴圈,而是在每次要畫之前,再去讀取 Kinect 的資料、並透過
GeneratePointCloud() 做轉換了∼而如果不打算重建多邊形、而是像 Heresy 直接一點一點畫出來的話,結果大概就會像上面的影片一樣了∼
若用 OpenGL 畫出來的話,基本上就是不要使用无穷循环,而是在每次要畫之前,再去讀取 Kinect 的資料、並透過
GeneratePointCloud() 做轉換∼而如果不打算重建多邊形、而是像 Heresy 直接一點一點畫出來的話,結果大概就會像上面的影片一樣∼
后记:
至此摘抄完毕,编译了程序,点云显示之后,测试程序检测无误....
**PCD数据获取:Kinect+OpenNI+PCL对接(代码)的更多相关文章
- Kinect+OpenNI+OpenCV使用
关于OpenNI,已经可以使用2.0,可以不再使用PrimeSense: 这里的是转载其他人的 OpenCV系列: 原文:http://blog.csdn.net/chenxin_130/articl ...
- delphi 连接oracle对接代码
selectt4.vclen60 as pat_d_codename,t4.vclen60 as pat_sexname,t1.pat_sex,t1.pat_d_code,t1.pat_in_no,t ...
- VS2010+PCL+openni配置
PCL中文论坛:http://www.pclcn.org/bbs/forum.php 1.安装 pcl 的完全安装包可以到: http://pointclouds.org/downloads/wind ...
- 三维重建:QT+OpenNI+Kinect图像校正
后记: 当时能不放弃这个方向是因为这里面涉及了一种很有效的三位场景存储方式,可能给出除图元建模之外的一种三维场景描述方式.这和Flash与位图的对比一样,基于图元的flash始终抵不过基于点描述的位图 ...
- PCL点云库中怎样读取指定的PCD文件,又一次命名,处理后保存到指定目录
我一直想把处理后的pcd文件重命名,然后放到指定的目录,尝试了好久最终做到了: 比方我想读取 "table_scene_lms400.pcd" 把它进行滤波处理,重命名为 &qu ...
- Kinect 总结---Kinect基本认识
玩了Kinect也有差不多一年的时间了,觉得Kinect是个挺好玩挺有未来的玩意.但是很经常做完了一次,下次又得重新看源码,没有把Kinect里的知识总结起来变为自己的知识,所以特意重新总结一下自己使 ...
- 使用OpenNI 2获取RGBD摄像头深度信息
NiViewer 安装好摄像头驱动和OpenNI后,在Tools文件夹中可以找到一个程序NiViewer.NiViewer的一些基本控制方法如下: 1. ESC关闭NiViewer程序 2. 右键可以 ...
- PCL中点云数据格式之间的转化
(1) 关于pcl::PCLPointCloud2::Ptr和pcl::PointCloud<pcl::PointXYZ>两中数据结构的区别 pcl::PointXYZ::PointXYZ ...
- Qt Load and Save PCL/PLY 加载和保存点云
Qt可以跟VTK和PCL等其他库联合使用,十分强大,下面的代码展示了如何使用Qt联合PCL库来加载和保存PCL/PLY格式的点云: 通过按钮加载点云: void QMainWindow::on_pb_ ...
随机推荐
- 如何查看系统的界面,比如费用申请单的序时簿界面引用的是哪一个ListUi.快捷键alt+shift+d 然后选中该ListUI大框框,就可以看到引用的是哪一个了.
如何查看系统的界面,比如费用申请单的序时簿界面引用的是哪一个ListUi.快捷键alt+shift+d 然后选中该ListUI大框框,就可以看到引用的是哪一个了.
- 【剑指Offer】30、连续子数组的最大和
题目描述: HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学.今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决.但是 ...
- XX-Net的完整教程
1.下载谷歌浏览器,安装. 2.百度搜索github,github中搜索XX-Net,下载稳定版 3.解压缩下载的文件夹,运行start.vbs文件.如果弹出管理员请求权限请允许,弹出防火墙警告,请允 ...
- autoware安装
1.Autoware的地址为https://github.com/CPFL/Autoware2.Install dependencies for Ubuntu 16.04 kinetic安装教程ins ...
- 爬虫系列(八) 用requests实现天气查询
这篇文章我们将使用 requests 调用天气查询接口,实现一个天气查询的小模块,下面先贴上最终的效果图 1.接口分析 虽然现在网络上有很多免费的天气查询接口,但是有很多网站都是需要注册登陆的,过程比 ...
- Python学习笔记之模块与包
一.模块 1.模块的概念 模块这一概念很大程度上是为了解决代码的可重用性而出现的,其实这一概念并没有多复杂,简单来说不过是一个后缀为 .py 的 Python 文件而已 例如,我在某个工作中经常需要打 ...
- Golang - 并发编程
目录 Golang - 并发编程 1. 并行和并发 2. go语言并发优势 3. goroutine是什么 4. 创建goroutine 5. runtime包 6. channel是什么 7. ch ...
- ELK之Logstash配置文件详解
Logstash 是一个开源的数据收集引擎,它具有备实时数据传输能力.它可以统一过滤来自不同源的数据,并按照开发者的制定的规范输出到目的地.它以插件的形式来组织功能,通过配置文件来描述需要插件做什么, ...
- Atcoder AGC031B Reversi (DP计数)
简单的计数题.(总算做出一道AGC的B题了,然而这场比赛我忘记打了233333) 题目链接: https://atcoder.jp/contests/agc031/tasks/agc031_b 题意: ...
- 0214常用的SQL语句
1MYSQL自己认为 \n 就是 换行. 如果想表达 \n 则用户必须以 \\n的方式来说明 SELECT CONCAT('"C:\\Program Files\\MySQL\\MySQL ...