Kinect for Windows SDK v2.0 开发笔记 (十八) Fusion 基本2D显示
来源:互联网 发布:java 给js传值 双引号 编辑:程序博客网 时间:2024/04/29 22:48
(转载请注明出处)
使用SDK: Kinect for Windows SDK v2.0 1409
在9月更新中, x86的Fusion终于可以使用了,这次说Fusion吧.
Fusion不再是所谓的“Fusion帧”了, 而是向一代靠齐,以NUI开头,可见算法与一代一样。
还是仅仅是降低代码移植成本?
所以找了找一代的说明:
Kinect Fusion能够基于深度图像,实时对场景进行重建。
设备能够使用GPU或者CPU进行计算:
enum _NUI_FUSION_RECONSTRUCTION_PROCESSOR_TYPE { NUI_FUSION_RECONSTRUCTION_PROCESSOR_TYPE_CPU= 1, NUI_FUSION_RECONSTRUCTION_PROCESSOR_TYPE_AMP= 2 } NUI_FUSION_RECONSTRUCTION_PROCESSOR_TYPE;
可见GPU加速使用的是C++AMP技术。
1代说明地址:http://msdn.microsoft.com/us-en/library/dn188670.aspx
Fusion将收集的数据慢慢"融合"起来
这是因为期间发动了“再融合”,从而使物品表面光滑(误)
Fusion工作管线:
需要的额外文件:
即Fusion的dll文件,使用命令:
xcopy /C /Y "$(KINECTSDK20_DIR)Redist\Fusion\x86\Kinect20.Fusion.dll" "$(OutDir)"
复制过来即可,头文件与库文件:
#include <NuiKinectFusionApi.h>
#pragma comment ( lib, "Kinect20.Fusion.lib" )
请注意以后SDK更新后,文件名的改变
基本Fusion步骤:
0. 设备检查:
Fusion对图形设备是有要求的,需要DX11的支持,可以进行设备检测:
// 获取设备信息:: 可以用于debug WCHAR description[MAX_PATH]; WCHAR instancePath[MAX_PATH]; UINT memorySize = 0; if (SUCCEEDED(hr)){ hr = NuiFusionGetDeviceInfo( m_processorType, m_deviceIndex, description, lengthof(description), instancePath, lengthof(instancePath), &memorySize ); if (hr == E_NUI_BADINDEX){ ::MessageBoxW(nullptr, L"需要DX11支持", L"错误", MB_ICONERROR); } }
NuiFusionGetDeviceInfo第一个参数是设备类型,就是 CPU还是GPU,
第二个是设备索引,标记-1使用默认设备。这次就-1,使用默认设备,下次枚举设备。
其他参数就不说了。
1. 创建Fusion 容积重建INuiFusionReconstruction
核心函数NuiFusionCreateReconstruction:
参数1: 容积重建参数
参数2: 设备类型
参数3: 设备索引
参数4: 世界到相机 坐标转换矩阵
参数5: 返回指针
参数1中:
typedef struct _NUI_FUSION_RECONSTRUCTION_PARAMETERS { FLOAT voxelsPerMeter; UINT voxelCountX; UINT voxelCountY; UINT voxelCountZ; } NUI_FUSION_RECONSTRUCTION_PARAMETERS;
从上到下依次是
每米体素(体积元素或者体积像素)数量
重建X轴体素数量
重建Y轴体素数量
重建Z轴体素数量
SDK中使用的数据为:
m_reconstructionParams.voxelsPerMeter = 256.f; m_reconstructionParams.voxelCountX = 384; m_reconstructionParams.voxelCountY = 384; m_reconstructionParams.voxelCountZ = 384;
即每米有256个体素,每两个临近的体素距离约为4mm.
建立了1.5m*1.5m*1.5m的容积,消耗内存384*384*384*4,200+MB(可能还有内存对齐消耗的内存)
GPU加速即显卡内存,CPU加速即系统内存,这可是一笔大买卖啊。
目前主流显存在1G~2G,差强人意。
创建后,可能会进行检错:
if (hr == E_NUI_GPU_FAIL){ ::MessageBoxW(nullptr, L"显卡不支持Fusion计算!\n或者 初始化失败", L"错误", MB_ICONERROR); } else if (hr == E_NUI_GPU_OUTOFMEMORY){ ::MessageBoxW(nullptr, L"显存不足", L"错误", MB_ICONERROR); }
1.5. 查看世界到容积坐标转换矩阵:
之前成功后,我们可以看看创建后的世界到容积坐标转换矩阵
if (SUCCEEDED(hr)){ hr = m_pReconstruction->GetCurrentWorldToVolumeTransform(&m_defaultWorldToVolumeTransform); }
设置断点后我们可以查看其值如下:
256 0 0 0
0 256 0 0
0 0 256 0
192 192 0 1
(0.75, 0.75, 1.5)经过转换后即为(384, 384, 384),即容积的边界点.
通过修改世界到容积转换矩阵可以控制重建范围.
2. 创建需要的Fusion图像帧:
Fusion图像帧储存了需要的数据,类型有:
typedef enum _NUI_FUSION_IMAGE_TYPE { NUI_FUSION_IMAGE_TYPE_INVALID= 0, NUI_FUSION_IMAGE_TYPE_COLOR= 1, NUI_FUSION_IMAGE_TYPE_FLOAT= 2, NUI_FUSION_IMAGE_TYPE_POINT_CLOUD= 3 } NUI_FUSION_IMAGE_TYPE;
即色彩、浮点与点云。
我们需要将收集的深度数据浮点化,再平滑化(可选),计算出点云后,输出表面(可选)与法线图像(可选)。
即需要5张Fusion图像帧
// 创建浮点深度帧 if (SUCCEEDED(hr)){ hr = NuiFusionCreateImageFrame( NUI_FUSION_IMAGE_TYPE_FLOAT, m_cDepthWidth, m_cDepthHeight, nullptr, &m_pDepthFloatImage ); } // 创建平滑浮点深度帧 if (SUCCEEDED(hr)){ hr = NuiFusionCreateImageFrame( NUI_FUSION_IMAGE_TYPE_FLOAT, m_cDepthWidth, m_cDepthHeight, nullptr, &m_pSmoothDepthFloatImage ); } // 创建点云帧 if (SUCCEEDED(hr)){ hr = NuiFusionCreateImageFrame( NUI_FUSION_IMAGE_TYPE_POINT_CLOUD, m_cDepthWidth, m_cDepthHeight, nullptr, &m_pPointCloud ); } // 创建Fusion图像帧 if (SUCCEEDED(hr)){ hr = NuiFusionCreateImageFrame( NUI_FUSION_IMAGE_TYPE_COLOR, m_cDepthWidth, m_cDepthHeight, nullptr, &m_pSurfaceImageFrame ); } // 创建Fusion法线帧 if (SUCCEEDED(hr)){ hr = NuiFusionCreateImageFrame( NUI_FUSION_IMAGE_TYPE_COLOR, m_cDepthWidth, m_cDepthHeight, nullptr, &m_pNormalImageFrame ); }
这样初始化基本完成了,不过需要重置一下:
INuiFusionReconstruction::ResetReconstruction
参数一: 新的目标 世界到相机 坐标转换矩阵
参数二: 新的目标 世界到容积 坐标转换矩阵
好了,初始化完成:
3. Fusion处理
Fusion是基于深度帧的,所以应该在深度图像中处理,
获取到深度数据后(前略):
转换为浮点型深度
INuiFusionReconstruction::DepthToDepthFloatFrame
之前说了,可以平滑化数据:
INuiFusionReconstruction::SmoothDepthFloatFrame
接下来处理该帧
INuiFusionReconstruction::ProcessFrame
这是一个较为高级的方法, 原文说了:
This is usually the camera pose result from the most recent call to the AlignPointClouds or AlignDepthFloatToReconstruction method.
可以调用这两个较低级的方法.
可能会处理错误:
// 检查错误 if (hr4f == E_NUI_FUSION_TRACKING_ERROR){ m_ImagaRenderer.error_info = L"Fusion跟踪失败, 请保证目标是静态的,\n请常试重建(单击窗口)"; } else if(SUCCEEDED(hr)){ m_ImagaRenderer.error_info = L"Fusion跟踪正常"; } else{ m_ImagaRenderer.error_info = L"Fusion跟踪失败"; }
计算出点云帧:
INuiFusionReconstruction::CalculatePointCloud
为点云帧着色(Shade)
NuiFusionShadePointCloud
输出表面与法线, 这将是我们显示的图像.
值得注意的是参数三:世界到BGR转换矩阵,
即将坐标XYZ转换为颜色BGR,Kinect中,XY可正可负,Z则一直为正,所以,我们这里
的转换矩阵是可以这样:
Matrix4 worldToBGRTransform = { 0.0f }; worldToBGRTransform.M11 = m_reconstructionParams.voxelsPerMeter / m_reconstructionParams.voxelCountX; worldToBGRTransform.M22 = m_reconstructionParams.voxelsPerMeter / m_reconstructionParams.voxelCountY; worldToBGRTransform.M33 = m_reconstructionParams.voxelsPerMeter / m_reconstructionParams.voxelCountZ; worldToBGRTransform.M41 = 0.5f; worldToBGRTransform.M42 = 0.5f; worldToBGRTransform.M43 = 0.0f; worldToBGRTransform.M44 = 1.0f;
我们还顺带计算了各个方法的耗时, 响应WM_LBUTTONUP消息以重建容积等等.
这就是成果图了:
可以看出各个都是吃时间的大东西。。。
这节就是说是基本的Fusion,代码下载地址:点击这里
- Kinect for Windows SDK v2.0 开发笔记 (十八) Fusion 基本2D显示
- Kinect for Windows SDK v2.0 开发笔记 (十七) 深度帧3D
- Kinect for Windows SDK v2.0 开发笔记 (一)环境
- Kinect for Windows SDK v2.0 开发笔记 (十二) 高清面部帧(3) 面部模型(2D)
- Kinect for Windows SDK v2.0 开发笔记 (十四) 高清面部帧(5) 面部模型 3D
- [译]Kinect for Windows SDK开发入门(十九):Kinect Fusion
- Kinect for Windows SDK开发入门(十九):Kinect Fusion
- Kinect for Windows SDK开发入门(十九):Kinect Fusion
- Kinect for Windows SDK开发入门:Kinect Fusion
- Kinect for Windows SDK v2.0 开发笔记 (二)彩色帧获取
- Kinect for Windows SDK v2.0 开发笔记 (三)深度帧与红外帧获取
- Kinect for Windows SDK v2.0 开发笔记 (四)玩家索引与绿屏技术
- Kinect for Windows SDK v2.0 开发笔记 (五)骨骼帧与笑面男
- Kinect for Windows SDK v2.0 开发笔记 (六)音频获取
- Kinect for Windows SDK v2.0 开发笔记 (七)语音识别(上)
- Kinect for Windows SDK v2.0 开发笔记 (八)语音识别(下)
- Kinect for Windows SDK v2.0 开发笔记 (九)面部帧获取
- Kinect for Windows SDK v2.0 开发笔记 (十) 高清面部帧(1) FACS 介绍
- FtpHelper ftp操作类库
- sh: 1: django-admin.py: not found
- 最长递增增子序列
- Gson解析嵌套多层的Json
- PL/SQL 连接64位 Oracle 11g数据库问题说明
- Kinect for Windows SDK v2.0 开发笔记 (十八) Fusion 基本2D显示
- 如何将应用安装到/system/app下
- Qt实现小功能之列表无限加载
- Spring事务配置的五种方式
- 基于C#的socket编程的TCP异步实现 ,包含服务器端与客户端源代码
- Fedora WARNING: 'aclocal-1.14' is missing on your system
- 【软件工程-UML 用例图与时序图总结】
- 数据序列化
- 针对CISCO防火墙日常维护(PIX、ASA)