赞
踩
博主的源码地址:https://github.com/sjy234sjy234/KinectFusion-ios
原论文:"KinectFusion: Real-time dense surface mapping and tracking."
之前的文章介绍了KinectFusion-ios的算法框架,主要由4个处理模块构成,并介绍了数据准备模块和ICP模块。本文主要介绍第3、4个处理模块——TSDF、Marching Cube。
一、TSDF
扩展阅读:https://blog.csdn.net/qq_31785865/article/details/78524429。
这里不展开介绍TSDF的原理,读者直接看扩展阅读的链接,或者搜索SDF和TSDF相关的论文阅读理解即可。TSDF用来存储和合成更新当前所有的深度数据,博主实现的KinectFusion-ios中取的TSDF的一些参数定义如下,见FusionDefinition.h文件
- #define TSDF_RESOLUTION 128
- #define TSDF_MAXWEIGHT 512
- // perlength, truncate and nearest are dynamic
- #define TSDF_PERLENGTH 1.8
- #define TSDF_TRUNCATE 10.0
- #define TSDF_NEAREST 300.0
其中,采用128x128x128的体素个数,是考虑到移动端的算力有限。TSDF算法的实现其实非常简单,源码包含在FuTsdfFusioner文件夹下。其中只包含一个类FuTsdfFusioner,实际上实现的是一个128x128x128尺寸的metal gpgpu核函数,逐体素的进行存储参数的更新。因此,TSDF的外部调用只有如下一行,代码在FusionProcessor.mm文件的processFrame方法中
- //tsdf fusion updater
- [_fuTsdfFusioner compute:m_currentDepthMapPyramid[0] intoTsdfVertexBuffer:m_tsdfVertexBuffer withIntrinsicXYZ2UVD:m_intrinsicXYZ2UVD[0] andTsdfParameter:m_tsdfParameter andTransform:m_globalToFrameTransform];
二、Marching Cube
扩展阅读:https://blog.csdn.net/noahzuo/article/details/78544609。
这里不展开介绍Marching Cube的原理,读者直接看扩展阅读的链接,或者搜索相关的论文阅读理解即可。Marching Cube用来提取TSDF体素中隐含存储的三维网格模型,实际上是提取TSDF中的0等值曲面。Marching Cube算法的实现源码包含在FuMarchingCube文件夹下,包含两个类:FuMCubeTraverse和FuMCubeExtract,分别对应Marching Cube算法的两步操作:遍历操作、提取操作。
首先,遍历操作,通过遍历TSDF网格,定位并记录下与0等值曲面相交的体素点;然后,提取操作,对于前面记录下来的体素点,利用预存的网格索引及线性插值方法,提取出三角形面片网格,得到重建的三维几何模型。
代码在FusionProcessor.mm文件的processFrame方法中的外部调用如下
- //marching cube
- int activeVoxelNumber = [_fuMCubeTraverse compute:m_tsdfVertexBuffer intoActiveVoxelInfo:m_mCubeActiveVoxelInfoBuffer withMCubeParameter:m_mCubeParameter];
- if(activeVoxelNumber==0)
- {
- NSLog(@"alert: no active voxel");
- m_mCubeExtractPointBuffer = nil;
- m_mCubeExtractNormalBuffer = nil;
- return NO;
- }
- else if(activeVoxelNumber>=m_mCubeParameter.maxActiveNumber)
- {
- NSLog(@"alert: too mush active voxels");
- m_mCubeExtractPointBuffer = nil;
- m_mCubeExtractNormalBuffer = nil;
- return NO;
- }
- else
- {
- void *baseAddress=m_mCubeActiveVoxelInfoBuffer.contents;
- ActiveVoxelInfo *activeVoxelInfo=(ActiveVoxelInfo*)baseAddress;
- for(int i=1;i<activeVoxelNumber;++i)
- {
- activeVoxelInfo[i].vertexNumber=activeVoxelInfo[i-1].vertexNumber+activeVoxelInfo[i].vertexNumber;
- }
- uint totalVertexNumber=activeVoxelInfo[activeVoxelNumber-1].vertexNumber;
- m_mCubeExtractPointBuffer = [_metalContext.device newBufferWithLength: 3 * totalVertexNumber * sizeof(float) options:MTLResourceOptionCPUCacheModeDefault];
- m_mCubeExtractNormalBuffer = [_metalContext.device newBufferWithLength: 3 * totalVertexNumber * sizeof(float) options:MTLResourceOptionCPUCacheModeDefault];
- [_fuMCubeExtract compute: m_mCubeActiveVoxelInfoBuffer andTsdfVertexBuffer: m_tsdfVertexBuffer withActiveVoxelNumber: activeVoxelNumber andTsdfParameter: m_tsdfParameter andMCubeParameter: m_mCubeParameter andOutMCubeExtractPointBufferT: m_mCubeExtractPointBuffer andOutMCubeExtractNormalBuffer: m_mCubeExtractNormalBuffer];
- }
第2行,执行遍历操作,并返回与0等值面相交的体素点的个数activeVoxelNumber。
第3-16行,activeVoxelNumber无效,则Marching Cube失败,重建失败。
第17-29行,activeVoxelNumber有效,执行提取操作。其中第19-27执行预分配内存空间,28行执行提取,完成Marching Cube算法,提取出来当前重建得到的三维几何网格模型。
三、总结
至此,KinectFusion-ios的实现就介绍完了。
目前,ios metal的使用者较少,因此网上可以参考的资料也较少。通过一轮KinectFusion-ios的源码介绍,就可以对ios metal的使用方法,特别是ios metal的gpgpu有了比较深入的理解。此外,如果是android端的gpgpu,可以使用renderscript进行实现。但是android端的处理器类型较多,gpgpu的生态不是很好。例如华为的手机自主研发的处理器,对renderscript的支持就不是很好,华为手机如果有更好的gpgpu语言选择,求留言告知。此外,苹果手机虽然从来不以性能为卖点,但是楼主亲身开发过ios和android相关的性能计算应用以后。发现苹果手机的性能,特别是gpu,确实是吊打android端的,谁开发谁知道~
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。