滚球法(Ball Pivoting)三维表面重建论文笔记

文章目录

  • 参考资料
  • 相关问题
  • 相关参数
  • 原理介绍
    • 1.基本概念
      • 1.1 顶点表示
      • 1.2 边表示
      • 1.3 数据结构
        • 1.3.1 元素
        • 1.3.2 存储方式
        • 1.3.3 查找方式
    • 2.算法实现
      • 2.1 查找种子点(Find Seed Triangle)
      • 2.2 球旋转(Ball Pivoting)
        • 2.2.1 旋转操作
        • 2.2.2 join和glue操作
        • 2.2.3 Out-of-Core extension
        • 2.2.4 多次传球(Multiple Passes)
  • Remarks

参考资料

[1] 原文
[2] 滚球法Github链接
[3] BPA PDF
[4] 文中提到的空洞填补论文(A Volumetric Method for BuildingComplex Modcls from Range Images)

相关问题

1.选择种子点(seed)时要确保三个顶点的法向相同(constitently oriented)
2.滚球法可改变半径并多次使用

相关参数

Lists: 数据点 σ i \sigma_i σi、法向量 n i n_i ni
front: 已连接边缘链表(Linked Lists of edges)的集合,初始组成为单闭合回路(single loop)

ps: front使用链表保存的原因:球沿着边缘旋转时,front将改变其拓扑结构
两种情况:
(1)遇到新数据:使用拓扑运算符
j o i n join join

(2)遇到以前使用过的数据点,使用拓扑运算符 g l u e glue glue
以上两个拓扑运算符能保证front在任意时刻都是链表结构


原理介绍

1.基本概念

1.1 顶点表示

每条边 e i j e_{ij} eij由两个端点 ( σ i , σ j ) (\sigma_i,\sigma_j) (σi,σj)表示,相对顶点(opposite vertex) σ o \sigma_o σo,连接此三个顶点的球的中心为 c i j o c_{ijo} cijo,半径为 ρ \rho ρ

球旋转操作:

添加三角形的连接操作(去除边 e i j e_{ij} eij并添加两条新边 e i k e_{ik} eik e k j e_{kj} ekj):


1.2 边表示

沿着front的同一个闭合回路连接前一条边(previous dege)和后一条边(next edge)
每条边有三种状态:

1. a c t i v e active active
用于旋转

2. b o u n d a r y boundary boundary不能旋转的边

3. f r o z e n frozen frozen

将所有信息与edge一起保存,可以使得旋转球的过程变得简单

1.3 数据结构

1.3.1 元素

b a l l _ p i v o t 和 f i n d _ s e e d _ t r i a n g l e ball\_pivot和find\_seed\_triangle ball_pivotfind_seed_triangle这两个过程需要对包含在空间领域内的点子集进行有效查找,可以使用 立方体单元格(a regular grid of cubic cells)或者体素(Voxel) 进行实现

1.3.2 存储方式

数据点保存在桶排序(Bucket sort)的链表(Lists)中,每个体素形成一个“桶”,体素的尺寸为 δ = 2 ρ \delta=2\rho δ=2ρ,相同体素内的数据点形成连续的子列表(“桶”),每个体素存储一个指向其子链表开头的指针(如果体素内没有数据则指向下一个体素)

1.3.3 查找方式

给定点 p p p,将它的坐标除以 δ \delta δ(体素尺寸即球直径)便可以很容易的查找它所属的体素(优化点1)
我们通常需要查找到点 p p p距离 2 ρ 2\rho 2ρ(球直径即体素尺寸)以内的所有点,这些点都包含在与V相邻的27个体素中(包括V本身)

2.算法实现

2.1 查找种子点(Find Seed Triangle)

(1)选取没有被使用过的任意点 σ \sigma σ
(2)按到 σ \sigma σ的距离考虑其邻域内的点对(pairs) σ a , σ b \sigma_a,\sigma_b σa,σb
(3)创建潜在的种子三角形 σ , σ a , σ b \sigma,\sigma_a,\sigma_b σσa,σb
(4)检查三角形法线与其顶点法线是否相同(如向外指向)
(5)检查中心在外半空间(猜测:利用法向判断方向)的半径为 ρ \rho ρ的球是否接触三个顶点并且不包含其他数据点
(6)找到所有有效种子点时停止
一些问题:
(1)对于主表面附近的一些噪声点(如配准时产生的重影)容易形成一些小的潜在种子三角形,虽然很容易通过后滤波去除掉,但是会浪费大量的计算资源(优化点2)

噪声样本导致产生了两层数据:

(2)每个体素只考虑将其中一个点作为种子三角形的顶点,在体素区域内的表面(surface)法向用该体素内所有点的法向的均值表示
(3)当找到seed后就开始用Pivoting操作进行重建,当不能继续旋转时就在停止位置寻找新的种子点,跳过所有包含已组成三角形顶点的体素(体素中有一个点是已找到的三角形中的顶点),当无法再找到seed时,停止算法


2.2 球旋转(Ball Pivoting)

2.2.1 旋转操作

球旋转操作:

其中:

m : m: m顶点 σ i 、 σ j \sigma_i、\sigma_j σiσj的中点
σ i 、 σ j : \sigma_i、\sigma_j: σiσj旋转edge的两个端点
σ x : \sigma_x: σx待检测连接的点(以 m m m为中心的 2 ρ 2\rho 2ρ邻域内的所有点)
c x : c_x: cx σ x 、 σ i 、 σ j \sigma_x、\sigma_i、\sigma_j σxσiσj接触的圆球的中心

所有的 c x c_x cx都位于环形轨迹(circular trajectory) γ \gamma γ上,通过计算球 ρ \rho ρ与圆 γ \gamma γ的交点便可计算出在 σ x \sigma_x σx处的圆中心点
记录下第一个接触(hit)到的点的坐标其对应的球中心
(可通过添加一些约束条件(Trivial rejection)以加速寻找第一个接触到的点)(优化点3)

2.2.2 join和glue操作

j o i n join join g l u e glue glue操作:

沿着边 e i j e_{ij} eij旋转,触碰的点为 σ k \sigma_k σk
情况一: σ k \sigma_k σk不是 m e s h mesh mesh中的点
输出三角形 ( σ k 、 σ i 、 σ j ) (\sigma_k、\sigma_i、\sigma_j) (σkσiσj)并移除边 e i j e_{ij} eij并添加两条新边 e i k e_{ik} eik e k j e_{kj} ekj

情况二: σ k \sigma_k σk已经是 m e s h mesh mesh中的点
(1) σ k \sigma_k σk是当前mesh内部的点
即当前mesh所有的边(edge)都没有包含顶点 σ k \sigma_k σk σ k \sigma_k σk不在当前mesh的边界(front)上)
e i j e_{ij} eij会被标记为 b o u n d a r y boundary boundary
(2) σ k \sigma_k σk是front(当前mesh边界edge)上的点
首先检查添加候选三角形不会造成非流形(nonmanifold)或不可定向流形(nonorientable manifold)
待查1:(检查可以通过检查连接(incident)到 σ k \sigma_k σk的edge是否存在(existence)以及其方向(orientation)来确定)
随后即可执行 j o i n 与 g l u e join与glue joinglue操作

2.2.3 Out-of-Core extension

核心外扩展(Out-of-Core extension)可以采取阵面推进法(advancing-front method)
文章中使用了简单数据切片方案(simple data-slicing scheme)
基本思想:缓存当前用于旋转(Pivoting)的数据集的一部分来转储不再使用(no longer being used)的数据(即已经找到三角形的区域),加载需要的数据
(1)使用两个轴对齐(Axis-aligned)的平面 π 0 \pi_0 π0 π 1 \pi_1 π1来定义用于旋转的活动工作区域
(2)初始化 π 0 \pi_0 π0的条件:没有数据在该平面之下(below)
(3) π 1 \pi_1 π1:在 π 0 \pi_0 π0之上(above)一定距离(用户指定distance)
(4)创建edge后,测试其端点是否高于(above) π 1 \pi_1 π1,是的话就将其标记为 f r o z e n frozen frozen
(5)当队列中所有的edge都被 f r o z e n frozen frozen后,向上抬升 π 0 \pi_0 π0 π 1 \pi_1 π1,并将所有 f r o z e n frozen frozen e d g e edge edge更新为 a c t i v e active active e d g e edge edge
(6)当相应的边界框进入或退出活动切片(slice)时,将从内存加载或丢失对应的数据点子集
(优化点4)


2.2.4 多次传球(Multiple Passes)

处理采样不均匀表面,可通过增加球半径进行多次传递的方法改善


Remarks

1.算法复杂度对于数据点数目上是线性的,并且是按照线性存储的
2.密度有界假设,此假设适用于扫描数据(scanned data),就算多次重复扫描,任意区域的点总数也是在已知的常量范围之内
3.算法大部分步骤都是复杂度为 O ( 1 ) O(1) O(1)的操作(如更新到队列、链接链表等)
4.每次 b a l l _ p i v o t ball\_pivot ball_pivot操作都要在不同的 m e s h   e d g e mesh\ edge mesh edge上进行,所以旋转次数(复杂度)为 O ( n ) O(n) O(n)
5.一次单独的 p i v o t pivot pivot需要识别 2 ρ 2\rho 2ρ邻域内的所有点,可以将候选点周围27个体素内的作为需识别的点,因为密度有界,所以这些点总数会限定在常数 B B B
6. f i n d _ s e e d _ t r i a n g l e find\_seed\_triangle find_seed_triangle依次选取未被使用过的点,因为每个点最多被使用一次,因此此操作的复杂度也为 O ( n ) O(n) O(n)
7.考虑待选seed是否被接受时,需要根据接触三个顶点的球对周围邻域内的所有点进行区分,因此复杂度为 O ( B 3 ) O(B^3) O(B3)
8.BPA的空间复杂度为 O ( n + L ) O(n+L) O(n+L) O ( L ) O(L) O(L)体素总数, O ( n ) O(n) O(n)是数据数目,可通过“切片”(阵面推进法)方法控制

你可能感兴趣的:(三维重建)