我想从布尔3D数组(180x180x197)中提取3D立方体(3x3x3)。这类似于scipy. nimage .measurements.label,但需要固定大小为(3x3x3)。有没有比使用for循环更快的方法?
在您的特殊情况下,我建议使用ndimage.minimum_filter假设你的数组叫做a。如下:
centers = ndimage.minimum_filter(a, 3, mode="constant")
将只包含数组中包含True的值然后,您可以使用带有默认结构的scipy. nimage .measurement .label对盒子进行分类,并可能识别连接的盒子。要找到它们,可以使用ndimage.measurement .find_objects
编辑:通过上面的方法,您将正确地获得数组中所有立方体的中心。澄清一下,我想这就是你第一个问题的答案。在评论中,事实证明,确实只需要不重叠的立方体。因此,需要分析minimum_filter的输出,我可以想象许多方法。可以使用以下命令在每个集群中只获取一个多维数据集:
s = ndimage.generate_binary_structure(3,3)
labels, num = ndimage.measurements.label(centers, s)
locations = ndimage.measurements.find_objects(labels)
locations = map(lambda slices: [slices[i].start for i in xrange(3)], locations)
现在的问题是丢失了不重叠但共用一个面的立方体。实际上,我们可以想象非常复杂的非重叠面共享立方体结构。当然,可以为这个问题找到几种解决方案(不重叠的多维数据集)。因此,从找到的中心中选择一组立方体是一项全新的任务,我认为你必须找到一个最适合你的。
一种方法是遍历所有解,并将找到的每个立方体设置为False:
get_starting_point = numpy.vectorize(lambda sl: sl.start) #to be applied on slices
s = ndimage.generate_binary_structure(3,3)
result = []
while True:
labels, num = ndimage.measurements.label(centers, s)
if not num:
break
locations = ndimage.measurements.find_objects(labels)
sp = get_starting_point(locations)
result.append(sp)
for p in sp:
centers[p[0]-1:p[0]+2, p[1]-1:p[1]+2, p[2]-1:p[2]+2] = False
numiter = len(results)
results = numpy.vstack(results)
我想只需要很少的迭代。
我希望这就是你要找的
get_starting_point = numpy.vectorize(lambda sl: sl.start)
s = ndimage.generate_binary_structure(3,3)
result = []
while True:
centers = ndimage.minimum_filter(b, 3, mode="constant")
labels, num = ndimage.measurements.label(centers, s)
if not num:
break
locations = ndimage.measurements.find_objects(labels)
sp = get_starting_point(locations)
for p in sp:
if numpy.all(a[p[0]-1:p[0]+2, p[1]-1:p[1]+2, p[2]-1:p[2]+2]):
result.append(p)
b[p[0]-1:p[0]+2, p[1]-1:p[1]+2, p[2]-1:p[2]+2] = False
numiter = len(result)
results = numpy.vstack(result)