我有一段代码,可以计算距离(未被分配的)最近的体素到一个已赋值的体素的距离。我有一个体素数组,其中一些体素已经被标量(1、2、3、4等)赋值,而一些体素为空(假设值为“0”)。下面的代码会找到距离未分配的体素最近的已分配的体素,并将该体素分配相同的标量。因此,标量为'0'的体素将根据最近的体素被赋予某个值(1或2或3等)。下面的代码可以运行,但是它需要太长时间。
是否有替代方法?或者您对如何进一步改进它有任何反馈?
"""#self.voxels是一个三维numpy数组"""
现在,如果我的体素数组的尺寸为(500,500,500),那么计算最近搜索所需的时间就不再高效。我该如何克服这个问题?并行计算能否减少时间(如果您知道是否可以并行化代码,请告诉我)?
一个可能的解决方案是,在cKDTree查询中添加n_jobs = -1参数,可以大幅提高计算速度。
"""#self.voxels是一个三维numpy数组"""
def fill_empty_voxel1(self,argx, argy, argz):
""" where # argx, argy, argz are the voxel location where the voxel is zero"""
argx1, argy1, argz1 = np.where(self.voxels!=0) # find the non zero voxels
a = np.column_stack((argx1, argy1, argz1))
b = np.column_stack((argx, argy, argz))
tree = cKDTree(a, leafsize=a.shape[0]+1)
distances, ndx = tree.query(b, k=1, distance_upper_bound= self.mean) # self.mean is a mean radius search value
argx2, argy2, argz2 = a[ndx][:][:,0],a[ndx][:][:,1],a[ndx][:][:,2]
self.voxels[argx,argy,argz] = self.voxels[argx2,argy2,argz2] # update the voxel array
示例
这是一个使用小数据集的简单示例:
import numpy as np
from scipy.spatial import cKDTree
import timeit
voxels = np.zeros((10,10,5), dtype=np.uint8)
voxels[1:2,:,:] = 5.
voxels[5:6,:,:] = 2.
voxels[:,3:4,:] = 1.
voxels[:,8:9,:] = 4.
argx, argy, argz = np.where(voxels==0)
tic=timeit.default_timer()
argx1, argy1, argz1 = np.where(voxels!=0) # non zero voxels
a = np.column_stack((argx1, argy1, argz1))
b = np.column_stack((argx, argy, argz))
tree = cKDTree(a, leafsize=a.shape[0]+1)
distances, ndx = tree.query(b, k=1, distance_upper_bound= 5.)
argx2, argy2, argz2 = a[ndx][:][:,0],a[ndx][:][:,1],a[ndx][:][:,2]
voxels[argx,argy,argz] = voxels[argx2,argy2,argz2]
toc=timeit.default_timer()
timetaken = toc - tic #elapsed time in seconds
print '\nTime to fill empty voxels', timetaken
用于可视化:
from mayavi import mlab
data = voxels.astype('float')
scalar_field = mlab.pipeline.scalar_field(data)
iso_surf = mlab.pipeline.iso_surface(scalar_field)
surf = mlab.pipeline.surface(scalar_field)
vol = mlab.pipeline.volume(scalar_field,vmin=0,vmax=data.max())
mlab.outline()
mlab.show()
现在,如果我的体素数组的尺寸为(500,500,500),那么计算最近搜索所需的时间就不再高效。我该如何克服这个问题?并行计算能否减少时间(如果您知道是否可以并行化代码,请告诉我)?
一个可能的解决方案是,在cKDTree查询中添加n_jobs = -1参数,可以大幅提高计算速度。
distances, ndx = tree.query(b, k=1, distance_upper_bound= 5., n_jobs=-1)
在一台13核CPU上,我能够在不到一个小时的时间内计算出一个尺寸为(400,100,100)的数组的距离。当我只使用一个处理器时,完成相同的数组需要大约18个小时的时间。 感谢@gsamaras提供的答案!