资料
motivation
在之前的表示中,会存储每个voxel的TSDF值。但是既然使用了截断SDF值,意味着不在截断范围内的体素组成的空间是free space,也就是没有必要的部分,对表面的重建不会有太大的帮助。因此可以设计一个新的数据结构来开发有效体素的稀疏性。
intro
这篇是用hash方法,设计了一个新数据结构,让TSDF可以动态增长。这种方法在大场景和精细建模上都可以使用。
related work
现在有三种三维重建方法:
- parametric methods, 直接把重叠的深度采样作平均,然后按照简单的topolopy来连接点。
- point-based , 把重叠的点融合。 render采用这种方法。这种在小物件、精细重建上经常使用。这种方法没法直接对表面建模。
- height map, 使用了2.5D的连续表面来表示重建。多用来进行建筑物建模。虽然很高效,但是不够精细。
- volumetric,使用raycasting等,把深度图转换成sdf,以概率来加权到voxel grid里面。缺陷是需要很大内存储存voxel,无法全局构建。
解决这些问题,有人提出用moving volume, 也有人用GPU-based octree。但是得不偿失,GPU上运行很慢。
algorithm
本文方法建立在volumetric上,使用hash 而不是设计复杂octree。而且不需要表面集合的先验知识。
主要有四点:
- 压缩TSDF,不适用octree
- 新TSDF可以fuse到hash table中,最小化collision。collision就是多个voxel被map到了同一个hash中。
- 去掉voxel block中的垃圾?
- Host 和GPU中用轻量级双向数据流, 达到unbounded reconstruction
- 使用raycasting等方法得到等值面。
pipeline
- alloc occupied blk
- update sdf in blk(integration)
- free voxel block that is far from surface. Ignore this step in esdf.
- pose etimation. ignore this step.
- streaming. leave it later, now just copy all.
数据结构
- voxel数据结构,里面没有坐标, hash entry里面有。根据hash key找到hash entry。
hash解决冲突
-
一个hash value对应一个bucket,每个bucket有4个entry. 一个coord经过hash函数计算得到一个hash value,如果对应的bucket里面有值,那么可以放到此entry后面一个entry。当寻找这个coord,(hashtable.find(coord)),先找到bucket,然后在bucket中遍历entry, 比较coord.
-
很少情况下,bucket overflow。这时候用链表思想,offset记录下一个entry到应该在的bucket地址的偏移。
-
find_insert: 先找bucket中每一个entry(中间碰到空格不要停,因为可能被删除了。esdf不删除,应该可以停),再找链表。还没找到,说明是新的,就插入。注意,不能同时写入一个bucket,会造成重复的entry或者链表不对。
-
delete
删除时分三种情况:
1、如果待删除的 hash entry 在 hash value 对应的 bucket 中,并且不是末尾元素,或者是末尾元素,但是末尾元素的 offset 是空,则在 bucket 直接将 hash entry 删除。
2、如果待删除的 hash entry 是 hash value 对应的 bucket 中的末尾元素,并且末尾元素的 offset 不是空,则需要根据 offset 找到链接的下一个 hash entry,并且将下一个 hash entry 移动到到末尾的 entry,
因为 bucket 末尾的entry 存储的是 bucket 满时,链接的别的 bucket 中 entry 地址,所以这里必须做移动。
3、如果待删除的 hash entry 在别的 bucket 中,删除该 entry 并且修改 offset