使用Kinect2.0获取点云以在GLUT中显示

这篇文章用来记录Kinect2.0如何生成点云.
以下示例源自Kinect提供的example修改完成,其名称会在小标题下方注解.
首先,要获取点云需要获取图像的深度数据和颜色数据.最后再将深度数据与颜色数据转为点云.
1.获取图像深度数据:
基于Depth Basic -D2D Example修改
HRESULT CMotionRecognition::GetDepthImage(){
if (!m_pDepthFrameReader)
{
return E_FAIL;
}
IDepthFrame * pDepthFrame = nullptr;
HRESULT hr = m_pDepthFrameReader->AcquireLatestFrame(&pDepthFrame);
if (SUCCEEDED(hr)){
IFrameDescription * pFrameDescription = nullptr;
USHORT nDepthMinReliableDistance = ;
USHORT nDepthMaxDistance = ;
UINT16 *pBuffer = NULL;
UINT nBufferSize = ;
if (SUCCEEDED(hr))
{
hr = pDepthFrame->get_FrameDescription(&pFrameDescription);
}
if (SUCCEEDED(hr))
{
hr = pFrameDescription->get_Width(&nDepthWidth);
}
if (SUCCEEDED(hr))
{
hr = pFrameDescription->get_Height(&nDepthHeight);
}
if (SUCCEEDED(hr))
{
hr = pDepthFrame->get_DepthMinReliableDistance(&nDepthMinReliableDistance);
}
if (SUCCEEDED(hr))
{
// In order to see the full range of depth (including the less reliable far field depth)
// we are setting nDepthMaxDistance to the extreme potential depth threshold
nDepthMaxDistance = USHRT_MAX;
// Note: If you wish to filter by reliable depth distance, uncomment the following line.
//// hr = pDepthFrame->get_DepthMaxReliableDistance(&nDepthMaxDistance);
}
if (SUCCEEDED(hr))
{
hr = pDepthFrame->AccessUnderlyingBuffer(&nBufferSize, &pBuffer);
}
if (SUCCEEDED(hr))
{
ConvertMat_depth(pBuffer, nDepthMinReliableDistance, nDepthMaxDistance);
}
SafeRelease(pFrameDescription);
}
SafeRelease(pDepthFrame);
return hr;
}
2.获取图像颜色数据:
基于Color Basic-D2D Example修改
HRESULT CMotionRecognition::GetColorImage(){
if (!m_pColorFrameReader)
{
return E_FAIL;
}
IColorFrame* pColorFrame = NULL;
HRESULT hr = m_pColorFrameReader->AcquireLatestFrame(&pColorFrame);
if (SUCCEEDED(hr))
{
INT64 nTime = ;
IFrameDescription* pFrameDescription = NULL;
ColorImageFormat imageFormat = ColorImageFormat_None;
UINT nBufferSize = ;
RGBQUAD *pBuffer = NULL;
hr = pColorFrame->get_RelativeTime(&nTime);
if (SUCCEEDED(hr))
{
hr = pColorFrame->get_FrameDescription(&pFrameDescription);
}
if (SUCCEEDED(hr))
{
hr = pFrameDescription->get_Width(&nColorWidth);
}
if (SUCCEEDED(hr))
{
hr = pFrameDescription->get_Height(&nColorHeight);
}
if (SUCCEEDED(hr))
{
hr = pColorFrame->get_RawColorImageFormat(&imageFormat);
}
if (SUCCEEDED(hr))
{
if (imageFormat == ColorImageFormat_Bgra)
{
hr = pColorFrame->AccessRawUnderlyingBuffer(&nBufferSize, reinterpret_cast<BYTE**>(&pBuffer));
}
else if (m_pColorRGBX)
{
pBuffer = m_pColorRGBX;
nBufferSize = nColorWidth * nColorHeight * sizeof(RGBQUAD);
hr = pColorFrame->CopyConvertedFrameDataToArray(nBufferSize, reinterpret_cast<BYTE*>(pBuffer), ColorImageFormat_Bgra);
}
else
{
hr = E_FAIL;
}
}
if (SUCCEEDED(hr))
{
ConvertMat_color(pBuffer, nColorWidth, nColorHeight);
}
SafeRelease(pFrameDescription);
}
SafeRelease(pColorFrame);
return hr;
}
3.处理图像数据函数
1/2中有一个ConvertMat_*函数,他是负责处理获取的图像颜色数据的,因为点云的转换需要深度数据和图像颜色数据,注意在这还可以创建OpenCV的Mat.
但这里只给出将获取的数据转存到pDepthBuffer(类中的一个成员)中的案例.
ConvertMat_depth()
void CMotionRecognition::ConvertMat_depth(const UINT16* _pBuffer, USHORT nMinDepth, USHORT nMaxDepth)
{
const UINT16
* pBuffer = _pBuffer,
* pBufferEnd = _pBuffer + (nDepthWidth * nDepthHeight); UINT16 * pDepthBufferTmp = pDepthBuffer; while (pBuffer < pBufferEnd)
{
*pDepthBufferTmp = *pBuffer; ++pDepthBufferTmp;
++pBuffer;
} }
ConvertMat_color()
void CMotionRecognition::ConvertMat_color(const RGBQUAD* _pBuffer, int nWidth, int nHeight)
{
const RGBQUAD
* pBuffer = _pBuffer,
* pBufferEnd = pBuffer + (nWidth * nHeight); RGBQUAD * pBufferTmp = m_pColorRGBX; while (pBuffer < pBufferEnd)
{
*pBufferTmp = *pBuffer;
++pBufferTmp;
++pBuffer;
} }
4.合成为点云:
基于CoordinateMappingBasics-D2D Example修改
osg::ref_ptr<osg::Node> CMotionRecognition::AssembleAsPointCloud(float _angle, int _axisX, int _axisY, int _axisZ)
{
if (!m_pKinectSensor)
{
return E_FAIL;
}
// osg空间坐标
osg::ref_ptr<osg::Vec3Array> point3dVec = new osg::Vec3Array();
// osg颜色值
osg::ref_ptr<osg::Vec4Array> colorVec = new osg::Vec4Array(); ICoordinateMapper * m_pCoordinateMapper = nullptr; HRESULT hr = m_pKinectSensor->get_CoordinateMapper(&m_pCoordinateMapper); for (size_t y = ; y != nDepthHeight; y++)
{
for (size_t x = ; x != nDepthWidth; x++)
{
DepthSpacePoint depthSpacePoint = { static_cast<float>(x), static_cast<float>(y) };
UINT16 currDepth = pDepthBuffer[y * nDepthWidth + x];
// Coordinate Mapping Depth to Color Space
ColorSpacePoint colorSpacePoint = { 0.0f, 0.0f };
m_pCoordinateMapper->MapDepthPointToColorSpace(depthSpacePoint, currDepth, &colorSpacePoint);
int colorX = static_cast<int>(std::floor(colorSpacePoint.X + 0.5f)),
colorY = static_cast<int>(std::floor(colorSpacePoint.Y + 0.5f));
if (( <= colorX) && (colorX < nColorWidth) && ( <= colorY) && (colorY < nColorHeight))
{
RGBQUAD color = m_pColorRGBX[colorY * nColorWidth + colorX];
colorVec->push_back(osg::Vec4f((float)color.rgbBlue / , (float)color.rgbGreen / , (float)color.rgbRed / , ));
}
// Coordinate Mapping Depth to Camera Space
CameraSpacePoint cameraSpacePoint = { 0.0f, 0.0f, 0.0f };
m_pCoordinateMapper->MapDepthPointToCameraSpace(depthSpacePoint, currDepth, &cameraSpacePoint);
if (( <= colorX) && (colorX < nColorWidth) && ( <= colorY) && (colorY < nColorHeight))
{
point3dVec->push_back(osg::Vec3(cameraSpacePoint.X, cameraSpacePoint.Y, cameraSpacePoint.Z));
}
}
} // 叶节点
osg::ref_ptr<osg::Geode> geode = new osg::Geode(); // 用来存储几何数据信息 构造图像 保存了顶点数组数据的渲染指令
osg::ref_ptr<osg::Geometry> geom = new osg::Geometry();
geom->setVertexArray(point3dVec.get()); geom->setColorArray(colorVec.get());
// 每一个颜色对应着一个顶点
geom->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
// 指定数据绘制的方式
geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POINTS, , point3dVec->size()));
// 加载到Geode中
geode->addDrawable(geom.get());
return geode;
}
下面是使用GLUT显示的结果:

可以看到帧率只有2.1左右,在后期要是在需要做处理的话则要更小了.
若谁还有更好的办法生成点云的话,欢迎留言 : )
使用Kinect2.0获取点云以在GLUT中显示的更多相关文章
- Kinect2.0获取数据
最近事情真是多,今天抽空研究一下Kinec2.0的数据获取! 系统要求 https://developer.microsoft.com/en-us/windows/kinect/hardware-se ...
- Kinect2.0获取关节姿态(Joint Orientation)
Bones Hierarchy 骨骼层次结构从SpineBase作为根节点开始,一直延伸到肢体末端(头.指尖.脚): 层级结构如下图所示: 通过IBody::GetJointOrientations函 ...
- 38)PHP,获取数据库数据并在html中显示(晋级5)
还有一个加了单例模式的,在第52个. 首先是我的文件关系: 我的主php文件是index.php,我的配置文件php是BBB.php 我的数据库操作文件是 b.php 我的html文件是lo ...
- 37)PHP,获取数据库数据并在html中显示(晋级4)
我的php文件和html文件的位置关系: 然后我的主php文件是b.php,我的那个配置文件是BBB.php,我的html文件是login.html 然后我的b.php代码展示: <?php c ...
- 36)PHP,获取数据库数据并在html中显示(晋级3)
首先展示我的html代码和php文件的位置关系: 然后我的php文件: <?php class db { public $host ;//= "localhost";//定义 ...
- 37)PHP,获取数据库值并在html中显示(晋级2)
下面的是上一个的改进版,我知道为啥我的那个有问题了,因为我的__construct()这个函数的里面的那个变量名字搞错了,哎,这是经常犯得毛病,傻了吧唧,气死我了. 之前的那个变量的代码样子: cla ...
- Kinect2.0点云数据获取
接上一篇:Kinect2.0获取数据 http://blog.csdn.net/jiaojialulu/article/details/53087988 博主好细心,代码基本上帖过来就可以用,注释掉的 ...
- C#微信公众号开发-高级接口-之网页授权oauth2.0获取用户基本信息(二)
C#微信公众号开发之网页授权oauth2.0获取用户基本信息(一) 中讲解了如果通过微信授权2.0snsapi_base获取已经关注用户的基本信息,然而很多情况下我们经常需要获取非关注用户的信息,方法 ...
- 使用Kinect2.0控制VREP中的虚拟模型
VREP中直接设置物体姿态的函数有3个: simSetObjectOrientation:通过欧拉角设置姿态 simSetObjectQuaternion:通过四元数设置姿态 simSetObject ...
随机推荐
- Android外派(安卓外派) — 长年提供安卓开发工程师外派业务(可签合同)
北京动点飞扬长年提供安卓工程师外派业务. 平均技术情况如下: 1.2~3年以上Android平台开发经验2.熟练掌握java技术,熟悉面向对象编程设计3.熟悉Android应用开发框架及Activit ...
- POJ #1141 - Brackets Sequence - TODO: POJ website issue
A bottom-up DP. To be honest, it is not easy to relate DP to this problem. Maybe, all "most&quo ...
- 剑指offer系列50--不用加减乘除做加法
[题目]写一个函数,求两个整数之和,要求在函数体内不得使用+.-.*./四则运算符号 * [思路]1 不计进位,直接位运算(异或方式可实现此运算,即1+0 0+1为1,0+0 1+1位0) * 2 与 ...
- (转)JS保留两位小数 四舍五入函数
本文转载自:http://www.cnblogs.com/446557021/archive/2011/10/13/2211047.html js 四舍五入函数 toFixed(),里面的参数 就是保 ...
- bzoj3035: 导弹防御塔
Description Freda的城堡——“Freda,城堡外发现了一些入侵者!”“喵...刚刚探究完了城堡建设的方案数,我要歇一会儿嘛lala~”“可是入侵者已经接近城堡了呀!”“别担心,rain ...
- 在 Perl 中使用 Getopt::Long 模块来接收用户命令行参数
我们在linux常常用到一个程序需要加入参数,现在了解一下 perl 中的有关控制参数的模块 Getopt::Long ,比直接使用 @ARGV 的数组强大多了.我想大家知道在 Linux 中有的参数 ...
- java学习笔记(三)字符串
字符串String 创建方法: 一·通过new创建 String str1= new String("abc"); 二 直接创建 String str2="abc ...
- Redis应用案例,查找某个值的范围(转)
本文来自Redis在Google Group上的一个问题,有一位同学发贴求助,说要解决如下的一个问题:他有一个IP范围对应地址的列表,现在需要给出一个IP的情况下,迅速的查找到这个IP在哪个范围,也就 ...
- Java事务处理全解析(二)——失败的案例
在本系列的上一篇文章中,我们讲到了Java事务处理的基本问题,并且讲到了Service层和DAO层,在本篇文章中,我们将以BankService为例学习一个事务处理失败的案例. BankService ...
- [Android Studio 1A] – 插件
关于android studio插件的使用,一直没有好的机会来研究,最近项目开发中需要统计项目的代码行数,所以就需要一个代码统计的插件.我选择的是 Statistic,下载地址是:https://pl ...