У меня есть код, который вычисляет ближайший воксел (который не назначен) к вокселу (который назначен). То есть у меня есть массив вокселей, у немногих вокселов уже есть назначенные значения скаляра (1,2,3,4 .... и т. Д.), А несколько вокселей пустые (скажем, значение «0»). Этот код ниже находит ближайший назначенный воксел для неназначенного воксела и присваивает этому вокселу тот же скаляр. Таким образом, вокселу со скаляром «0» будет присвоено значение (1 или 2 или 3, ...) на основе ближайшего воксела. Этот код ниже работает, но требуется слишком много времени. Есть ли альтернатива этому? или если у вас есть какие-либо отзывы о том, как его улучшить?Как ускорить поиск ближайшего соседа с помощью python?
"" "# self.voxels является 3D 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()
Нет w, если у меня есть размер массива вокселей как что-то вроде (500 500 500), то время, затрачиваемое на вычисление ближайшего поиска, уже неэффективно. Как я могу это преодолеть? Может ли параллельное вычисление сократить время (я понятия не имею, могу ли я распараллелить код, если да, дайте мне знать)?
Потенциальное Исправление:
я мог бы существенно улучшить время вычисления путем добавления n_jobs = -1 параметра в запросе cKDTree.
distances, ndx = tree.query(b, k=1, distance_upper_bound= 5., n_jobs=-1)
я смог вычислить расстояния в менее чем за час для массива (400,100,100) на 13 основного процессора в. Я попробовал с 1 процессором, и для завершения того же массива требуется около 18 часов. Спасибо @gsamaras за ответ!
В качестве предположения вы можете попробовать методы из http://scikit-learn.org/stable/modules/generated/sklearn.neighbors.NearestNeighbors.html#sklearn.neighbors.NearestNeighbors, но я думаю, что проблема в емкость памяти. (500 500 500) - действительно гигантский объект. –
Здравствуйте, @gsamaras, Спасибо за ответ. Я сделал tr с помощью подхода sklearn-соседа, но время вычисления не оказывает большого влияния. Я ждал, если кто-нибудь еще придет с любым другим ответом, прежде чем я приму ваш ответ как последний. Поскольку ваш ответ намного ближе к тому, что я просил, я приму ваш ответ. Еще раз спасибо! –
Хмм, я вижу @RavirajpurohitPurushottamr, спасибо за ваш вклад, удачи! – gsamaras