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

GLSL truncated signed distance representation (TSDF) implementation

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

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

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

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

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

如何以有效的方式呈现这种有符号距离表示的实际技术水平?

你走在正确的轨道上,这是一个雄心勃勃的项目,但如果你能做到,那就太棒了。

首先,有必要了解一下这些东西是如何工作的。识别 TSDF 的原始论文由 Curless 和 Levoy 撰写,相当平易近人 - 副本是 here。后来有很多变化,但这是起点。

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

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

现在你有了 TSFD 数据表示,每一帧你都需要这样做:

1.在世界坐标中计算出相机相对于 TSDF 的位置。 通常你假设你是时间 t=0 的原点,然后测量你相对于前一帧的平移和旋转。最常见的方法是使用一种称为迭代最近点的算法(ICP) You could implement this yourself or use a library like PCL 虽然我不确定他们是否有移动版本。我建议你在没有这个的情况下开始,只需保留你的相机和场景静止不动,稍后再移动。

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

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

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

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

d) 使用像素 x 和 y 坐标加上深度和您的相机属性将此点投影回 space 以获得对应于该深度的 3D 点

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

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

将所有深度图集成到 TSDF 后,您可以通过光线追踪或提取等值面(3D 网格)并在另一个包中查看来可视化结果。

真正 有用的论文 here。这是一些实际在 PC 上为自己实现 Kinect Fusion 的学生的实验报告。虽然您仍然需要学习 CUDA 或类似软件才能实现它,但它几乎是一个循序渐进的指南

您还可以在 GitHub 上查看我的源代码以获取想法,但适用于适用性的所有正常免责声明均适用。

祝你好运!

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

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

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

中的那个点相关联

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

您只需创建一组顶点和渲染点,即可在 GLES 上使用这些渲染器。关于如何执行此操作的讨论 here

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