在可以透過 OpenNI 讀取到 Kinect 的深度、色彩資訊之後,其實就可以試著用這些資訊,來重建 3D 的環境做顯示了~不過實際上,在前面的範例中所讀到的深度資訊,都算是原始資料,而且座標軸也都是感應器二維影像的座標系統,如果要重建 3D 場景的話,這些資訊都還是需要換算的;所幸,OpenNI 在 Depth Generator 已經有提供 ConvertProjectiveToRealWorld() 和ConvertRealWorldToProjective() 這兩個函式,可以幫助程式開發者快速地進行座標轉換了!

而如果把直接把這些 3D 的點位附加顏色、用 OpenGL 畫出來呢,就大概會是下面影片的樣子吧~

當然,point cloud 不見得是最好的顯示方式,有需要的話也可以重建出多邊形再畫,不過多邊形的重建已經算是另一個主題了,所以 Heresy 也不打算在這邊討論;另外,Heresy 在這篇也不會提及 OpenGL 顯示的部分,只會提供簡單的範例,示範如何建立出這些 point cloud 而已。

而為了儲存這些點的位置以及顏色資訊,這邊先定義了一個簡單的結構、SColorPoint3D:

structSColorPoint3D
{floatX;floatY;floatZ;floatR;floatG;floatB;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

而為了方便起見,Heresy 把座標轉換的部分寫成一個函式 GeneratePointCloud(),其內容如下:

voidGeneratePointCloud( xn::DepthGenerator& rDepthGen,constXnDepthPixel* pDepth,constXnRGB24Pixel* pImage,vector<SColorPoint3D>& vPointCloud )
{// 1. number of point is the number of 2D image pixel
xn::DepthMetaData mDepthMD;rDepthGen.GetMetaData( mDepthMD );unsignedintuPointNum = mDepthMD.FullXRes() * mDepthMD.FullYRes();// 2. build the data structure for convert
XnPoint3D* pDepthPointSet =newXnPoint3D[ uPointNum ];unsignedinti, 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 =newXnPoint3D[ 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,這樣可以減少一些索引值的計算;而因為這樣修改,之前讀取彩色影像的程式也要由

constXnUInt8* pImageMap = mImageGenerator.GetImageMap();

修改為

constXnRGB24Pixel* pImageMap = mImageGenerator.GetRGB24ImageMap();

而在函式內容的部分,第一段的部分主要是透過取得 depth generator 的 meta-data:xn::DepthMetaData 來做簡單的大小、索引計算;如果不想這樣用的話,其實也是可以直接用 640 x 480 這樣固定的值來做計算,不過就是要和之前在 SetMapOutputMode() 所設定的解析度一致就是了。

第二部分「build the data structure for convert」,則是將深度影像的 640 x 480 個點,都轉換為 XnPoint3D 形式的一為陣列,已準備進行之後的座標轉換。

第三部分「un-project points to real world」則就是實際進行轉換的部分了。這邊要把座標由影像的座標系統轉換到 3D 座標系統,主要是用 Depth Generator 的 ConvertProjectiveToRealWorld() 這個函式;而它的使用方法也很簡單,只要告訴他要轉換的點的數量(uPointNum)、把要轉換的點用陣列的形式傳(const XnPoint3D*)進去,並給他一塊已經 allocate 好的 XnPoint3D 陣列(p3DPointSet),就可以自動進行轉換了~

第四部份 Heresy 則是再用一個迴圈去掃過全部的點,並把深度為 0 的點給去掉(因為這些點是代表是 Kinect 沒有辦法判定深度的部分)、並和顏色的資訊一起轉換為 SColorPoint3D 的形式,丟到 vPointCloud 裡儲存下來了。

(這個動作其實也可以在第二步的時候先做掉,但是在那邊做顏色的部分會比較麻煩就是了。)

而回到主程式的部分,本來讀取資料的程式是:

// 8. read dataeResult = mContext.WaitNoneUpdateAll();if( eResult == XN_STATUS_OK )
{// 9a. get the depth map
constXnDepthPixel*  pDepthMap = mDepthGenerator.GetDepthMap();// 9b. get the image map
constXnUInt8*    pImageMap = mImageGenerator.GetImageMap();}

前面也提過了,Heresy 這邊不打算提及用 OpenGL 顯示的部分,所以這邊為了不停地更新資料,所以改用一個無窮迴圈的形式來不停地更新資料、並進行座標轉換;而轉換後的結果,也很簡單地只輸出它的點的數目了。

// 8. read data
vector<SColorPoint3D> vPointCloud;while(true)
{eResult = mContext.WaitNoneUpdateAll();// 9a. get the depth map
constXnDepthPixel*  pDepthMap = mDepthGenerator.GetDepthMap();// 9b. get the image map
constXnRGB24Pixel*  pImageMap = mImageGenerator.GetRGB24ImageMap();// 10 generate point cloud
vPointCloud.clear();GeneratePointCloud( mDepthGenerator, pDepthMap, pImageMap, vPointCloud );cout <<"Point number: "<< vPointCloud.size() << endl;
}

如果是要用 OpenGL 畫出來的話,基本上就是不要使用無窮迴圈,而是在每次要畫之前,再去讀取 Kinect 的資料、並透過 GeneratePointCloud() 做轉換了~而如果不打算重建多邊形、而是像 Heresy 直接一點一點畫出來的話,結果大概就會像上面的影片一樣了~

trackback: http://kheresy.wordpress.com/2011/01/25/build_3d_point_cloud_via_openni/

转载于:https://www.cnblogs.com/JohnShao/archive/2011/05/22/2053496.html

透過 OpenNI 建立 Kinect 3D Point Cloud相关推荐

  1. 5、透過 OpenNI / NITE 分析人體骨架(上)(非原创)

    5. 透過 OpenNI / NITE 分析人體骨架(上)(非原创) http://viml.nchc.org.tw/blog/paper_info.php?CLASS_ID=1&SUB_ID ...

  2. 《3D Point Cloud Registration for Localization using a Deep Neural Network Auto-Encoder》读书笔记

    3D Point Cloud Registration for Localization using a Deep Neural Network Auto-Encoder 题目:基于深度神经网络自编码 ...

  3. Learning Multiview 3D point Cloud Registration论文阅读笔记

    Learning multiview 3D point cloud registration Abstract 提出了一种全新的,端到端的,可学习的多视角三维点云配准算法. 多视角配准往往需要两个阶段 ...

  4. Kinect+OpenNI学习笔记之11(OpenNI驱动kinect手势相关的类的设计)

    前言 本文所设计的类主要是和人体的手部打交道的,与人体的检测,姿势校正,骨架跟踪没有关系,所以本次类的设计中是在前面的OpenNI+Kinect系列博文基础上去掉那些与手势无关的驱动,较小代码量负担. ...

  5. 点云生成-PointFlow: 3D Point Cloud Generation with Continuous Normalizing Flows

    点云生成-PointFlow: 3D Point Cloud Generation with Continuous Normalizing Flows 简介 论文 摘要 1.introduction ...

  6. 企业私有云的建立—基于Ubuntu Enterprise Cloud(3)

    2019独角兽企业重金招聘Python工程师标准>>> 企业私有云的建立-基于Ubuntu Enterprise Cloud(3) 2011-01-14 16:40:51 标签: U ...

  7. 使用 ssmtp 於 shell 透過 Gmail 寄信

    有很多程式於 bash shell 執行, 執行完要自動寄信出去, 但是最近都被 Google 退信, 最好的方法是透過 Gmail 直接寄信. 本來是要另外寫隻 script 來做這種事, 剛剛發現 ...

  8. 3D Point Cloud Descriptors in Hand-crafted and Deep Learning Age: State-of-the-Art

    一.introduction 1.The development of 3D point cloud descriptor is going through two major stages: (1) ...

  9. 如何透過JavaScript來觸發LinkButton的PostBack,呼叫後端的程式

    緣起 這一篇最終的目的,是希望能夠透過JavaScript來觸發Server端的Function來做一些事情,在這個過程中,我們透過觀察LinkButton的PostBack運作,進而想出如何使用Ja ...

最新文章

  1. 如何调试分析Android中发生的tombstone
  2. 支付宝的高可用与容灾架构演进
  3. jvm性能调优 - 11J线上VM调优案例分享
  4. python中pos的用法_Python:数组、队列及堆栈的使用(list用法)--转
  5. ubuntu18.04安装python的mysqlclient==1.4.6报错ERROR Command errored out with exit status 1python setup
  6. ubuntu16.04下编译安装OpenCV
  7. 【转】 差分约束系统详解(转化为最短路) (概念)
  8. 最长高地(51Nod-2509)
  9. Windows环境下多个tomcat启动方法
  10. 解封装(二):初始化解封装avformat_open_input,各参数分析,以及简单流程
  11. docker-for-windows配置了阿里云镜像,仍然无法获得链接:(Client.Timeout exceeded while awaiting headers)
  12. codevs 1143 纪念品分组
  13. 第三回 基类中的方法,应该根据实际情况,虚的虚,抽象的抽象!
  14. paip.解决中文url路径的问题图片文件不能显示
  15. 关于无法卸载和安装VISIO2010的问题
  16. 最新版计算机知识超全题库,超全的计算机基础知识题库.doc
  17. Android逆向之路---让我们试试另一种方法看漫画-(1)
  18. VS2015 还是VS2017 好用_如何卸载清理vs2017前vs2015,vs2013等版本
  19. 巴西龟饲养日志----巴西龟成长速度
  20. CA机构介绍(Certificate Authority 域名SSL证书颁发机构)

热门文章

  1. 使用service实现登录、权限控制
  2. mysql Table 'plugin' already exists
  3. Linux 下判断Server 内存是否不足
  4. 换换口味,体验一下Mandriva
  5. 高仿网易新闻频道选择器
  6. 最课程阶段大作业05:污水处理系统以及百度地图
  7. 如何禁止用户名,密码自动填充
  8. PowerDesigner逆向生成
  9. Android OpenCV Manager简介
  10. 数学图形之克莱因瓶(klein bottle)