GLSL截断符号距离表示(TSDF)实现

时间:2016-11-12 07:56:35

标签: c++ opengl-es glsl point-clouds

我期待实现RGB-D图像的模型重建。在手机上首选。为此,我读到了,所有这些都是通过TSDF表示完成的。我现在阅读了大量关于层次结构和其他想法的论文来加快这一点,但我的问题是,我仍然不知道如何实际实现这种表示。

如果我有一个大小为n的体网格,那么n x n x n我希望在每个体素中存储有符号的距离,重量和颜色信息。我唯一的猜测是,我必须为每个体素位置构建一组离散的点。并使用GLSL" paint"所有这些点并计算最近的距离。但是,计算这个n ^ 3次似乎不太好或没有效率。

我怎么能想象实现这样的TSDF表示?

问题是,我唯一的想法是渲染体素网格以存储在有符号距离的数据中。但是对于每个深度图,我必须再次渲染所有体素并计算所有距离。有没有办法以相反的方式渲染它?

那么我不能渲染深度图的点并在体素网格中存储信息吗?

实际的艺术状态如何以有效的方式呈现这样的有符号距离表示?

2 个答案:

答案 0 :(得分:8)

你走在正确的轨道上,这是一个雄心勃勃的项目,但如果你能做到这一点非常酷。

首先,值得了解这些事情是如何运作的。标识TSDF的原始论文是由Curless和Levoy完成并且相当平易近人 - 副本是here。有许多后来的变化,但这是起点。

其次,您需要创建nxnxn存储,如您所述。这很快变大了。例如,如果您想要400x400x400体素的RGB数据和浮点值的距离和重量,那么这将是768MB的GPU内存 - 您可能需要检查移动设备上可用的GPU内存量。是的,我说GPU因为......

虽然你可以在CPU上实现玩具解决方案,但如果你想拥有任何类型的性能,你真的需要认真对待GPU编程。我在Intel i7 CPU笔记本电脑上构建了早期版本。不可否认,我没有花时间优化它,但整合单个深度图像花了几十秒。如果你想获得实时(30Hz),那么你需要一些GPU编程。

现在您有了TSFD数据表示,您需要执行以下每个帧:

<强> 1。根据世界坐标确定摄像机相对于TSDF的位置。 通常假设您是时间t = 0时的原点,然后测量相对于前一帧的相对平移和旋转。最常见的方法是使用称为迭代最近点(ICP)的算法您可以自己实现此方法或使用像PCL这样的库,但我不确定他们是否有移动设备版。我建议你在没有这个的情况下开始使用,只需保持你的相机和场景静止不动,然后再运动。

<强> 2。将您拥有的深度图像集成到TSDF中这意味着使用下一个深度图像更新 TSDF。您不会丢弃迄今为止的信息,而是将新信息与旧信息合并。 您可以通过迭代TSDF中的每个体素来执行此操作:

a)计算从体素中心到相机的距离

b)将点投影到深度相机的图像平面以获得像素坐标(使用上面获得的外部相机位置和可轻松搜索Kinect的相机内部参数)

c)在该像素坐标处查找深度图中的深度

d)使用像素x和y坐标加深度和相机属性将此点投射回太空以获得与该深度对应的3D点

e)使用值distance_from_step_d更新当前体素距离的值 - distance_from_step_a(更新通常是现有值加上新值的加权平均值)。

您可以对体素颜色使用类似的方法。

将所有深度贴图集成到TSDF后,您可以通过光线跟踪或提取iso曲面(3D网格)并在另一个包中查看结果来显示结果。

非常有用的论文可以帮助您here。这是一些实际在PC上实现Kinect Fusion的学生的实验报告。它几乎是一步一步的指导,尽管你仍然需要学习CUDA或类似的实现它

您也可以在GitHub上查看我的源代码,了解所有关于适用性的正常免责声明。

祝你好运!

答案 1 :(得分:3)

在我发布我的其他答案之后,我想到了另一种方法,它似乎与您问题的第二部分相匹配,但它绝对不是重建,也不涉及使用TSDF。它实际上是一个可视化,但 更简单:)

每帧都会获得RGB和深度图像。假设这些图像被注册,即RGB图像中(x,y)处的像素表示与深度图像中(x,y)处的像素相同的像素,则可以创建使用RGB数据着色的密集点云。要做到这一点,你会:

对于深度图中的每个像素 a)使用相机的内在矩阵(K),像素坐标和该点处地图中的深度值将该点投影到相机坐标中的3D点 b)将同一像素的RGB值与空间中的该点相关联

所以现在你有一个(可能是640x480)结构的数组,如{x​​,y,z,r,g,b}

只需创建一组顶点和渲染点,就可以在GLES上渲染这些渲染。有关如何执行此操作的讨论here

使用这种方法,您可以每帧丢弃数据并从头开始重做。重要的是,您没有获得重建曲面,也没有使用TSDF。你可以得到漂亮的结果,但它不是重建。