[英]Locating indices of points within 3D bounding box using numpy logical_and or where?
I have a large list of points (x, y, z)
.我有很多点
(x, y, z)
。
points = np.random.rand(999).reshape(333, 3)
I also have two points representing the minimum and maximum corners of a 3D bounding box representing points of interest我还有两个点代表 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]
I am trying to select indices in points
which lie within this bounding box but am having issues.我正在尝试 select 索引位于此边界框内但有问题的
points
。 I originally attempted using np.where
我最初尝试使用
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
)
Though this results in虽然这会导致
ValueError: The truth value of an array with more than one element is ambiguous.
because and
'ing the results of each comparison is ambiguous (from my understand numpy
can't decide to do element-wise or entire array and
).因为
and
'ing 每次比较的结果都是模棱两可的(据我了解numpy
不能决定逐元素或整个数组and
)。
I found an SO answer which provides a solution in the 2D case and I've attempted to expand it to the 3D case我找到了一个 SO answer,它在 2D 案例中提供了一个解决方案,我试图将其扩展到 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)))
Though this seems to always result in no points being selected ( poid_inds = (False)
, if I remove the np.all
I find all indices are False
) even after running the SSCCE below multiple times.尽管这似乎总是导致没有选择任何点(
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))
What is the proper use of np.where
or np.logical_and
in this case to locate the points within the described bounding box?在这种情况下,正确使用
np.where
或np.logical_and
来定位所描述的边界框中的点是什么?
I have found a compact solution which utilizes np.where
, functools.reduce
, and np.intersect1d
我找到了一个紧凑的解决方案,它利用
np.where
、 functools.reduce
和np.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)
))
On large lists >100M points this is many times faster than iterating through the points "manually".在大于 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)
If points
is a Numpy array you can use &
instead of np.logical_and
to write this as:如果
points
是 Numpy 数组,则可以使用&
而不是np.logical_and
将其写为:
mask_x = (points[:, 0] >= min_x) & (points[:, 0] <= max_x)
mask_y = (points[:, 1] >= min_y) & (points[:, 1] <= max_y)
mask_z = (points[:, 2] >= min_z) & (points[:, 2] <= max_z)
mask = mask_x & mask_y & mask_z
indices = np.where(mask)
Which, from a quick test, seems to be faster than the solution by KDecker.从快速测试来看,这似乎比 KDecker 的解决方案更快。
The problem is that you are comparing an array with an element.问题是您正在将数组与元素进行比较。
points[:, 0] > min_x
An array cannot be compared with a single element.数组不能与单个元素进行比较。
Instead, you need to use a loop.相反,您需要使用循环。
for i in range(333):
points[i:0] > min_x
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.