【问题标题】:Locating indices of points within 3D bounding box using numpy logical_and or where?使用 numpy logical_and 或在哪里定位 3D 边界框中的点索引?
【发布时间】:2021-03-11 17:25:05
【问题描述】:

我有一大堆积分(x, y, z)

points = np.random.rand(999).reshape(333, 3)

我还有两个点代表兴趣点的 3D 边界框的最小和最大角

min_point = np.random.rand(3)
min_x, min_y, min_z = min_point[0], min_point[1], min_point[2]

max_point = np.random.rand(3)
max_x, max_y, max_z = max_point[0], max_point[1], max_point[2]

我正在尝试在points 中选择位于此边界框内但遇到问题的索引。我最初尝试使用np.where

poi_inds = np.where(
    points[:, 0] > min_x and points[:, 0] < max_x and
    points[:, 1] > min_y and points[:, 1] < max_y and
    points[:, 2] > min_z and points[:, 2] < max_z
)

虽然这会导致

ValueError: The truth value of an array with more than one element is ambiguous.

因为and'ing 每次比较的结果都是模棱两可的(据我了解,numpy 无法决定逐元素还是整个数组 and)。

我找到了一个提供 a solution in the 2D case 的 SO 答案,并且我尝试将 to expand it 用于 3D 案例

poi_inds = np.all(np.logical_and.reduce((
    points[:, 0] > min_x, points[:, 0] < max_x,
    points[:, 1] > min_y, points[:, 1] < max_y,
    points[:, 2] > min_z, points[:, 2] < max_z)))

尽管这似乎总是导致没有点被选中(poid_inds = (False),如果我删除np.all,我发现所有索引都是False),即使在多次运行以下SSCCE之后也是如此。

import numpy as np

points = np.random.rand(999).reshape(333, 3)

rand_pt0 = np.random.rand(3)
rand_pt1 = np.random.rand(3)
# Ensure the minimum point is always less than the maximum
min_point = np.array([
    rand_pt0[0] if rand_pt0[0] < rand_pt1[0] else rand_pt1[0],
    rand_pt0[1] if rand_pt0[1] < rand_pt1[1] else rand_pt1[1],
    rand_pt0[2] if rand_pt0[2] < rand_pt1[2] else rand_pt1[2],
])
max_point = np.array([
    rand_pt1[0] if rand_pt0[0] < rand_pt1[0] else rand_pt0[0],
    rand_pt1[1] if rand_pt0[1] < rand_pt1[1] else rand_pt0[1],
    rand_pt1[2] if rand_pt0[2] < rand_pt1[2] else rand_pt0[2],
])

min_x, min_y, min_z = min_point[0], min_point[1], min_point[2]
max_x, max_y, max_z = max_point[0], max_point[1], max_point[2]

# poi_inds = np.where(
#     points[:, 0] > min_x and points[:, 0] < max_x and
#     points[:, 1] > min_y and points[:, 1] < max_y and
#     points[:, 2] > min_z and points[:, 2] < max_z
# )

poi_inds = np.logical_and.reduce((
    points[:, 0] > min_x, points[:, 0] < max_x,
    points[:, 1] > min_y, points[:, 1] < max_y,
    points[:, 2] > min_z, points[:, 2] < max_z))

在这种情况下正确使用np.wherenp.logical_and 来定位所描述的边界框内的点?

【问题讨论】:

    标签: python numpy


    【解决方案1】:

    我找到了一个使用np.wherefunctools.reducenp.intersect1d 的紧凑型解决方案

    from functools import reduce
    
    poi_inds = reduce(np.intersect1d, (
        np.where(points[:, 0] > min_x),
        np.where(points[:, 0] < max_x),
        np.where(points[:, 1] > min_y),
        np.where(points[:, 1] < max_y),
        np.where(points[:, 2] > min_z),
        np.where(points[:, 2] < max_z)
    ))
    

    在大于 100M 个点的大型列表中,这比“手动”遍历点快很多倍。

    poi_inds = []
    for ind, pt in enumerate(points):
        if min_x < pt[0] < max_x and min_y < pt[1] < max_y and min_z < pt[2] < max_z:
            poi_inds.append(ind)
    

    【讨论】:

      【解决方案2】:

      问题在于您将数组与元素进行比较。

      points[:, 0] > min_x
      

      数组不能与单个元素进行比较。
      相反,您需要使用循环。

      for i in range(333):
          points[i:0] > min_x
      

      【讨论】:

        猜你喜欢
        • 2017-07-10
        • 1970-01-01
        • 2016-01-08
        • 2020-04-12
        • 2013-06-03
        • 2018-04-17
        • 2012-03-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多