【发布时间】:2020-01-04 10:16:21
【问题描述】:
我只需要选择 3d 二进制数组的非零 3d 部分(或者布尔数组的真实值)。目前我可以通过一系列使用 np.any 的“for”循环来做到这一点,但这确实有效,但看起来很尴尬和缓慢,所以目前正在研究一种更直接的方式来完成这项任务。
我对 numpy 比较陌生,所以我尝试过的方法包括 a) 使用 np.nonzero,它返回我不知道该怎么做的索引,b)boolean array indexing,和c)boolean masks。对于简单的 2d 数组,我通常可以理解这些方法中的每一种,但我很难理解这些方法之间的差异,并且无法让它们为 3d 数组返回正确的值。
这是我当前的函数,它返回一个非零值的 3D 数组:
def real_size(arr3):
true_0 = []
true_1 = []
true_2 = []
print(f'The input array shape is: {arr3.shape}')
for zero_ in range (0, arr3.shape[0]):
if arr3[zero_].any()==True:
true_0.append(zero_)
for one_ in range (0, arr3.shape[1]):
if arr3[:,one_,:].any()==True:
true_1.append(one_)
for two_ in range (0, arr3.shape[2]):
if arr3[:,:,two_].any()==True:
true_2.append(two_)
arr4 = arr3[min(true_0):max(true_0) + 1, min(true_1):max(true_1) + 1, min(true_2):max(true_2) + 1]
print(f'The nonzero area is: {arr4.shape}')
return arr4
# Then use it on a small test array:
test_array = np.zeros([2, 3, 4], dtype = int)
test_array[0:2, 0:2, 0:2] = 1
#The function call works and prints out as expected:
non_zero = real_size(test_array)
>> The input array shape is: (2, 3, 4)
>> The nonzero area is: (2, 2, 2)
# So, the array is correct, but likely not the best way to get there:
non_zero
>> array([[[1, 1],
[1, 1]],
[[1, 1],
[1, 1]]])
代码工作正常,但我在更大、更复杂的数组上使用它,我认为这不是一个合适的方法。任何关于更直接的方法来完成这项工作的想法将不胜感激。如果输入数组在原始数组中有两个单独的非零 3d 区域,我也会担心错误和结果。
为了澄清问题,我需要将一个或多个 3D 部分作为一个或多个 3d 数组返回,该数组以原始较大的数组开头。返回的数组不应在三维空间中的任何给定外部平面中包含无关的零(或错误值)。仅获取非零值的索引(反之亦然)本身并不能解决问题。
【问题讨论】:
-
如果 1 随机分散在原始数组中会怎样?
-
我不确定为什么你需要这样做,所以我只是猜测,但如果你试图降低操作的速度和内存稀疏数组,那么您可以考虑使用一些稀疏数据结构,例如 scipy.sparse 提供的。
-
该应用程序是为 3D 打印应用程序减少一个数组。所以要在场内旋转或平移形状,我只需要操纵正体素区域。
标签: python numpy numpy-ndarray