Spherical Voxelization

  • 标签: voxelization
  • AI 摘要: 文档介绍了球面体素化的过程,包括重要的类和方法,如ConvertToSphericalVoxel和spherical_voxel_optimized,详细解释了参数及其作用。球面体素化通过将点云转换为球面坐标系,利用自适应采样权重来平衡不同纬度区域的点密度,从而有效捕捉几何特征。文中还提到C++绑定的sv.compute函数,负责体素特征的计算与填充,确保在特征计算中考虑邻近体素的信息。
  • 最相关链接: https://github.com/CVLAB-Unibo/compass

Spherical Voxelization

参考链接:

代码组成:

ConvertToSphericalVoxel类:最高接口,实例化一个converter类,调用convert转换局部点云

spherical_voxel_optimized方法:在convert中调用,实现转换,先转换到球面坐标系,然后进行体素化

spherical_voxel.compute方法:最终实现体素化,用pybind绑定C++代码最终实现

ConvertToSphericalVoxel

from utils import geometry as ug

class ConvertToSphericalVoxel():

    """
Convert point cloud to spherical voxel [beta = 2 * bandwidth, alfa = 2 * bandwidth, num_radial_division].
Alfa in [0, 2pi], Beta in [0, pi]
""" def __init__(self, bandwidth, radius_support, num_radial_division, num_points, random_sampling): self.bandwidth = bandwidth
self.radius_support = radius_support
self.num_radial_division = num_radial_division
self.num_points = num_points
self.random_sampling = random_sampling def __call__(self, point_cloud): features, pts_normed = ug.spherical_voxel_optimized(points=point_cloud,
size_bandwidth=self.bandwidth,
size_radial_divisions=self.num_radial_division,
radius_support=self.radius_support,
do_random_sampling=self.random_sampling,
num_random_points=self.num_points) return features, pts_normed
……

参数解释:

  • bandwidth: 球面体素化的带宽,通常用于定义球面信号的分辨率。它决定了角度方向上的采样密度(球面坐标系的\(\beta\),\(\alpha\)),影响了球面信号的分辨率,PRIN, LMVD, Compess等设置为24。
  • radius_support: 支持半径,定义了local patch的支持半径,也就是说它确定了从关键点向外延伸的范围内哪些点将被纳入local patch。
  • num_radial_division: 表示径向(从关键点向外辐射的方向)上的分割数目。它影响了在径向方向上球面信号的分辨率。
  • num_points: 采样点的数量,这个值与local patch的固定点数一致(即1024点),确保输入到转换过程中的点数是一致的,这对于后续处理和模型输入非常重要。
  • random_sampling: 控制是否在从点云中选择点时进行随机采样,设置为 True 使得在局部区域内的点采样更加多样化,避免由于局部密度过高或过低而导致的信息丢失。随机采样可以让网络更具鲁棒性,适应不同点云的分布。

spherical_voxel_optimized

def spherical_voxel_optimized(points: np.ndarray, size_bandwidth: int, size_radial_divisions: int,
radius_support: float, do_random_sampling: bool, num_random_points: int) \
-> Tuple[np.ndarray, np.ndarray]:
"""Compute spherical voxel using the C++ code. Compute Spherical Voxel signal as defined in:
Pointwise Rotation-Invariant Network withAdaptive Sampling and 3D Spherical Voxel Convolution.
Yang You, Yujing Lou, Qi Liu, Yu-Wing Tai, Weiming Wang, Lizhuang Ma and Cewu Lu.
AAAI 2020. :param points: the points to convert.
:param size_bandwidth: alpha and beta bandwidth.
:param size_radial_divisions: the number of bins along radial dimension.
:param radius_support: the radius used to compute the points in the support.
:param do_random_sampling: if true a subset of random points will be used to compute the spherical voxel.
:param num_random_points: the number of points to keep if do_random_sampling is true. :return: A tuple containing:
The spherical voxel, shape(size_radial_divisions, 2 * size_bandwidth, 2 * size_bandwidth).
The points used to compute the signal normalized according the the farthest point.
"""
if do_random_sampling:
min_limit = 1 if points.shape[0] > 1 else 0
indices_random = np.random.randint(min_limit, points.shape[0], num_random_points)
points = points[indices_random] pts_norm = np.linalg.norm(points, axis=1)
# Scale points to fit unit sphere
pts_normed = points / pts_norm[:, None]
pts_normed = np.clip(pts_normed, -1, 1) pts_s2_coord = S2.change_coordinates(pts_normed, p_from='C', p_to='S')
# Convert to spherical voxel indices
pts_s2_coord[:, 0] *= 2 * size_bandwidth / np.pi # [0, pi]
pts_s2_coord[:, 1] *= size_bandwidth / np.pi # raw 2*size_bandwidth/2*np.pi
pts_s2_coord[:, 1][pts_s2_coord[:, 1] < 0] += 2 * size_bandwidth # Adaptive sampling factor sin{pi*[(1/2,..., 2*size_bandwidth+1/2)/(2*size_bandwidth)]}
# 能更好的聚合点云信息,但是也会导致更多的形变,有得必有失
daas_weights = np.sin(np.pi * (2 * np.arange(2 * size_bandwidth) + 1) / 4 / size_bandwidth).astype(np.float32)
voxel = np.asarray(sv.compute(pts_on_s2=pts_s2_coord,
pts_norm=pts_norm,
size_bandwidth=size_bandwidth,
size_radial_divisions=size_radial_divisions,
radius_support=radius_support,
daas_weights=daas_weights))
pts_normed = points / np.max(pts_norm)
return voxel.astype(np.float32), pts_normed.astype(np.float32)
  • pts_norm是local patch的点云径向距离,所以local patch输入的时候最好经过对于关键点的中心化操作,不然径向距离会是关于坐标系原点的。
  • S2.change_coordinates 用于将点云从笛卡尔坐标系转换成球面坐标系,球面坐标系解释见WIKI,简单来说就是两个坐标,维度角度坐标\beta,和经度角度坐标\alpha
  • daas_weights是自适应权重:
    • 采样密度平衡:在球面坐标系中,由于纬度(通常用β表示)不同区域的面积差异,不同区域的点密度会有所不同。例如,在球面的极地区域(纬度接近0π的区域),同样的角度变化可能覆盖的球面面积较小,而在赤道区域,面积较大。为了避免在这些区域中出现过度或不足的采样,自适应采样权重用于平衡不同纬度区域的影响。
    • 信息保持:通过在不同的纬度上使用不同的采样权重,可以更精确地保留球面上重要的几何特征,特别是在特定的关键区域。这样可以确保球面信号在高纬度和低纬度区域都能有效地捕捉到有意义的几何信息。
  • sv.compute 用于体素转换。

sv.compute

该函数是用pybind绑定的C++方法,文件为spherical_voxel.cc ,代码解释如下:

初始化

    const float interval = radius_support / (size_radial_divisions);
std::vector<std::vector<std::vector<std::vector<std::vector<float> > > > > grids;
std::vector<std::vector<std::vector<float> > > features; grids.resize(size_radial_divisions);
features.resize(size_radial_divisions); for (auto &beta: grids) {
beta.resize(2 * size_bandwidth);
for (auto &alpha: beta) {
alpha.resize(2 * size_bandwidth);
}
} for (auto &beta: features) {
beta.resize(2 * size_bandwidth);
for (auto &alpha: beta) {
alpha.resize(2 * size_bandwidth, 0);
}
}
  • interval表示径向分割下每个体素的径向长度
  • grids用来存储每个体素覆盖的所有点,可以通过下面的初始化看到,会初始化径向,维度,经度,每个体素是一种voxel
  • feature用来存储最终每个体素的特征(特征是密度特征)

grids填充

    // mapping the points to the voxel grid
for (size_t i = 0; i < pts_on_s2.size(); i++) {
int r_idx = int(pts_norm[i] / interval);
// except for the points radius larger than radius_support
if (r_idx > size_radial_divisions - 1) r_idx = size_radial_divisions - 1; int beta_idx = int(pts_on_s2[i][0] + 0.5f);
if (beta_idx > 2 * size_bandwidth - 1) beta_idx = 2 * size_bandwidth - 1; int alpha_idx = int(pts_on_s2[i][1] + 0.5f);
if (alpha_idx > 2 * size_bandwidth - 1) alpha_idx = 2 * size_bandwidth - 1; grids[r_idx][beta_idx][alpha_idx].emplace_back(std::vector<float>{pts_norm[i], pts_on_s2[i][0], pts_on_s2[i][1]});
}

这里会遍历每个点,计算每个点的径向体素所用r_idx,纬度体素索引beta_idx,经度体素索引alpha_idx ,然后push到对应的体素里面。

feature计算

首先计算每个体素的经度左右特征计算边界leftright(也就是说每个体素的特征计算并不仅仅只考虑本体素内部,还有一些可能出现的相邻体素),这里计算左右边界就用到自适应权重,维度高的,左右边界会宽一些。

之后根据左右边界访问对应体素,并取出体素中所有点,基于径向距离确定点是否靠近本体素中心,越靠近该点的特征权重越大([0, 1])。

然后考虑径向相邻体素内部的点,用于本体素的特征计算,因为从径向考虑,点分布相对连续,需要补充这样的信息。

最后计算本体素的特征(密度特征(加过权的点个数))

    // compute the feature of each voxel
for (size_t i = 0; i < size_radial_divisions; i++) {
for (size_t j = 0; j < 2 * size_bandwidth; j++) {
for (size_t k = 0; k < 2 * size_bandwidth; k++) {
const float left = std::max(0.f, k - 0.5f / daas_weights[j]);
const float right = std::min(2.f * size_bandwidth, k + 0.5f / daas_weights[j]);
float sum = 0.f;
int cnt = 0; for (int m = int(left + 0.5f); m < int(right + 0.5f); m++) {
for (int n = 0; n < grids[i][j][m].size(); n++) {
if (grids[i][j][m][n][2] > left && grids[i][j][m][n][2] < right) {
sum += 1.f - std::abs(grids[i][j][m][n][0] / interval - (i + 1)); // radial feature weight
cnt++;
}
} // 在实际情况中,点云数据可能分布在两个相邻的径向分割之间,
// 尤其是当点的径向距离位于两个径向分割的边界附近时。
// 为了防止因单纯考虑当前径向分割而导致信息的丢失,
// 代码会查找相邻径向分割中满足条件的点,并将它们的贡献也加到当前体素单元的特征值中。
if (i < size_radial_divisions - 1) {
for (int n = 0; n < grids[i + 1][j][m].size(); n++) {
if (grids[i + 1][j][m][n][2] > left && grids[i + 1][j][m][n][2] < right) {
sum += 1.f - std::abs(grids[i + 1][j][m][n][0] / interval - (i + 1));
cnt++;
}
}
}
} // 与径向分割不同,纬度分割(即 beta 方向)代表的是球面坐标中的角度,
// 分割的区域代表不同的“环”或“带”。
// 在这种情况下,每个纬度分割对应的球面区域是明确的,
// 且这些分割区域之间没有交叉,因此点不会“跨越”到另一个纬度分割。 if (cnt > 0) {
features[i][j][k] = sum / cnt;
}
}
}
}

Spherical Voxelization的更多相关文章

  1. 球谐光照(Spherical Harmonics Lighting)及其应用-实验篇

    简介 之前在一篇实时深度图优化的论文中看到球谐光照(Spherical Harmonics Lighting)的应用,在查阅了许许多多资料之后还是无法完全理解,我个人觉得如果之前对实时渲染技术不是很了 ...

  2. 球面墨卡托(Spherical Mercator)

    地理信息描述空间位置相关的信息,在空间位置的表达中,需要基于空间参照系来保证数据精度以及不同数据源之间的相互叠加/空间分析操作.自Google Maps与2005年发布以来,电子地图服务与普通民众的日 ...

  3. Spherical CNNs代码配置过程

    ICLR18 best paper: Spherical CNNs 论文链接:https://arxiv.org/abs/1801.10130 GITHUB地址:https://github.com/ ...

  4. 3D Spherical Geometry Kernel( Geometry Kernels) CGAL 4.13 -User Manual

    Introduction The goal of the 3D spherical kernel is to offer to the user a large set of functionalit ...

  5. 数学图形(2.14)Spherical helix曲线

    从http://mathworld.wolfram.com/SphericalHelix.html上找到如下一些关于该曲线的说明,不过似乎他的公式和我的脚本完全是两个东西.. The tangent  ...

  6. Fisheye projections from spherical maps [转]

    Fisheye projections from spherical maps Written by Paul Bourke May 2003, software updated January 20 ...

  7. Converting a fisheye image into a panoramic, spherical or perspective projection [转]

    Converting a fisheye image into a panoramic, spherical or perspective projection Written by Paul Bou ...

  8. Spherical Harmonics Lighting

    [转自:http://www.cnblogs.com/daniagger/archive/2012/05/29/2524133.html] 1.背景知识 1.1 光照表示 之前我们都只考虑光源点和物体 ...

  9. 三维卷积:全景图像Spherical CNNs(Code)

    卷积神经网络(CNN)可以很好的处理二维平面图像的问题.然而,对球面图像进行处理需求日益增加.例如,对无人机.机器人.自动驾驶汽车.分子回归问题.全球天气和气候模型的全方位视觉处理问题. 将球形信号的 ...

  10. j2s7s300 refers to jaco v2 7DOF spherical 3fingers

    <?xml version="1.0"?> <!-- j2s7s300 refers to jaco v2 7DOF spherical 3fingers --& ...

随机推荐

  1. IIS部署错误HTTP Error 500.36 ASP.NET Core IIS hosting failure(out-of-process)

    错误提示 HTTP Error 500.36 - ASP.NET Core IIS hosting failure (out-of-process) The out of process reques ...

  2. Nunjucks

    Nunjucks是什么东东?其实它是一个模板引擎. 那什么是模板引擎? 模板引擎就是基于模板配合数据构造出字符串输出的一个组件.比如下面的函数就是一个模板引擎: function examResult ...

  3. Mysql 添加字段、修改字段、删除字段、新增

    导读 Mysql数据类型,点我直达 创建表 语法: create table 表名( 字段名1 字段类型2 约束条件1 说明1, 字段名2 字段类型2 约束条件2 说明2 ) 约束条件: commen ...

  4. 如何优雅地使用Mybatis逆向工程生成类

    文/朱季谦 1.环境:SpringBoot 2.在pom.xml文件里引入相关依赖: 1 <plugin> 2 <groupId>org.mybatis.generator&l ...

  5. Stopwatch 类来测量时间间隔

    使用 Stopwatch 类来测量时间间隔. 以下是一个示例代码,展示如何记录 Excel 导入的用时: ' 创建 Stopwatch 实例 Dim stopwatch As New Stopwatc ...

  6. oeasy教您玩转vim - 21 - 状态横条

    状态横条 回忆上节课内容 我们上次研究了标尺 标尺 开启 se ru 关闭 se noru 行号 开启 se nu 关闭 se nonu 命令位置 开启 se showcmd 关闭 se noshow ...

  7. odoo 开发入门教程系列-一个新应用

    一个新应用 房地产广告模块 假设需要开发一个房地产模块,该模块覆盖未包含在标准模块集中特定业务领域. 以下为包含一些广告的主列表视图 form视图顶层区域概括了房产的重要信息,比如name,Prope ...

  8. 题解:P9777 [HUSTFC 2023] Fujisaki 讨厌数学

    令 \(f(n)=x^{n}+x^{-n}\). 可以发现 \(f(n)f(m)=x^{n-m}+x^{m-n}+x^{n+m}+x^{-n-m}=f(n-m)+f(m+n)\). 若 \(m=1\) ...

  9. PHP进阶

    只是简要说明起原理和用法,具体可以百度 abstract 抽象类 抽象类是指在 class 前加了 abstract 关键字且存在抽象方法,不带{},如public function test() i ...

  10. RHCA rh442 003 系统资源 查看硬件 tuned调优

    监控工具 zabbix 监控具体业务,列如数据库.触发式事件(断网 硬盘坏一个) 普罗米修斯 给容器做监控 管理人员,如何知道几千台服务器哪些出了问题,这得需要zabbix 系统硬件资源 cpu [r ...