锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

Open3D Distance Queries 距离查询

时间:2023-12-26 06:37:02 功勋高压水密连接器

Distance Queries 距离查询

Open3D 中的类RaycastingScene提供一组距离查询,可用于将三角形网格转换为隐藏函数,查询表面距离或确定点是否位于网格中。
在本教程中,我们将展示如何生成这些查询,以及如何处理几何和 3D 机器学习中使用的网格生成隐藏表示。

Converting a mesh to an implicit representation

采用三角网格初始化RaycastingScene

# Load mesh and convert to open3d.t.geometry.TriangleMesh armadillo_data = o3d.data.ArmadilloMesh() mesh = o3d.io.read_triangle_mesh(armadillo_data.path) mesh = o3d.t.geometry.TriangleMesh.from_legacy(mesh)  # Create a scene and add the triangle mesh scene = o3d.t.geometry.RaycastingScene() _ = scene.add_triangles(mesh)  # we do not need the geometry ID for mesh 

计算单个点的距离和占用

RaycastingScene 它还提供了计算查询点占用率的函数。

query_point = o3d.core.Tensor([[10, 10, 10]], dtype=o3d.core.Dtype.Float32)  # Compute distance of the query point from the surface unsigned_distance = scene.compute_distance(query_point) signed_distance = scene.compute_signed_distance(query_point) occupancy = scene.compute_occupancy(query_point)  print("unsigned distance", unsigned_distance.numpy()) print("signed_distance", signed_distance.numpy()) print("occupancy", occupancy.numpy()) 

虽然无符号距离可以一直计算,但符号距离和占用率只有在网格水密、内外明确定义时才有效。
如果查询点位于网格中,则符号距离为负。对于网格点,占用率为 0.对于网格中的点,占用率为 1。

计算多个点与网格之间的距离

RaycastingScene允许一次进行多个查询。例如,我们可以通过一个[N,3]张量表示N个查询点,可用于随机抽样一个体积,训练机器学习中的隐式神经。

min_bound = mesh.vertex['positions'].min(0).numpy() max_bound = mesh.vertex['positions'].max(0).numpy()

N = 256
query_points = np.random.uniform(low=min_bound, high=max_bound,
                                 size=[N, 3]).astype(np.float32)

# Compute the signed distance for N random points
signed_distance = scene.compute_signed_distance(query_points)

RaycastingScene允许使用任意数量的前导维度来组织查询点。要查询格网(grid)的有符号距离,我们可以执行以下操作

xyz_range = np.linspace(min_bound, max_bound, num=32)

# query_points is a [32,32,32,3] array ..
query_points = np.stack(np.meshgrid(*xyz_range.T), axis=-1).astype(np.float32)

# signed distance is a [32,32,32] array
signed_distance = scene.compute_signed_distance(query_points)

# We can visualize a slice of the distance field directly with matplotlib
plt.imshow(signed_distance.numpy()[:, :, 15])

同样的过程也适用于 RaycastingScene.compute_distance和RaycastingScene.compute_occupancy ,可用于生成无符号距离和占用字段。

Computing distances with closest point queries 使用最近点查询计算距离

距离函数建立在compute_closest_points()函数之上。在这一部分中,我们将重新实现有符号距离,并演示如何利用函数compute_closest_points()返回的其他信息。

初始化

我们首先使用两个三角形网格初始化RaycastingScene。两个网格都是水密的,我们将放置它们,使它们之间没有交集。

cube = o3d.t.geometry.TriangleMesh.from_legacy(
    o3d.geometry.TriangleMesh.create_box().translate([-1.2, -1.2, 0]))
sphere = o3d.t.geometry.TriangleMesh.from_legacy(
    o3d.geometry.TriangleMesh.create_sphere(0.5).translate([0.7, 0.8, 0]))

scene = o3d.t.geometry.RaycastingScene()
# Add triangle meshes and remember ids
mesh_ids = { 
        }
mesh_ids[scene.add_triangles(cube)] = 'cube'
mesh_ids[scene.add_triangles(sphere)] = 'sphere'

计算表面上最近的点

RaycastingScene.compute_closest_points()可以计算表面上相对于查询点的最近点。

query_point = o3d.core.Tensor([[0, 0, 0]], dtype=o3d.core.Dtype.Float32)

# We compute the closest point on the surface for the point at position [0,0,0].
ans = scene.compute_closest_points(query_point)

# Compute_closest_points provides the point on the surface, the geometry id,
# and the primitive id.
# The dictionary keys are
#. points
#. geometry_ids
#. primitive_ids
print('The closest point on the surface is', ans['points'].numpy())
print('The closest point is on the surface of the',
      mesh_ids[ans['geometry_ids'][0].item()])
print('The closest point belongs to triangle', ans['primitive_ids'][0].item())

为了计算点是在内部还是外部,我们可以从查询点开始投射光线,并计算交集的数量。

rays = np.concatenate(
    [query_point.numpy(),
     np.ones(query_point.shape, dtype=np.float32)],
    axis=-1)
intersection_counts = scene.count_intersections(rays).numpy()
# A point is inside if the number of intersections with the scene is even
# This sssumes that inside and outside is we ll defined for the scene.
is_inside = intersection_counts % 2 == 1

我们可以将其组合成一个函数,以创建一个返回附加信息的特殊有符号距离函数:

def compute_signed_distance_and_closest_goemetry(query_points: np.ndarray):
    closest_points = scene.compute_closest_points(query_points)
    distance = np.linalg.norm(query_points - closest_points['points'].numpy(),
                              axis=-1)
    rays = np.concatenate([query_points, np.ones_like(query_points)], axis=-1)
    intersection_counts = scene.count_intersections(rays).numpy()
    is_inside = intersection_counts % 2 == 1
    distance[is_inside] *= -1
    return distance, closest_points['geometry_ids'].numpy()

我们可以使用该函数创建具有距离和几何 ID 信息的网格

# compute range
xyz_range = np.linspace([-2, -2, -2], [2, 2, 2], num=32)
# query_points is a [32,32,32,3] array ..
query_points = np.stack(np.meshgrid(*xyz_range.T), axis=-1).astype(np.float32)

sdf, closest_geom = compute_signed_distance_and_closest_goemetry(query_points)

# We can visualize a slice of the grids directly with matplotlib
fig, axes = plt.subplots(1, 2)
axes[0].imshow(sdf[:, :, 16])
axes[1].imshow(closest_geom[:, :, 16])
锐单商城拥有海量元器件数据手册IC替代型号,打造电子元器件IC百科大全!

相关文章