Ich habe einen Code, der das nächste Voxel (das nicht zugewiesen ist) zu einem Voxel (das zugewiesen ist) berechnet. Das heißt, ich habe eine Reihe von Voxeln, nur wenige Voxel haben bereits skalare (1,2,3,4 .... etc) Werte und wenige Voxel sind leer (sagen wir mal einen Wert von '0'). Dieser Code findet das nächste zugewiesene Voxel für ein nicht zugewiesenes Voxel und weist diesem Voxel den gleichen Skalar zu. Ein Voxel mit einem Skalar '0' erhält also einen Wert (1 oder 2 oder 3, ...) basierend auf dem nächsten Voxel. Dieser Code unten funktioniert, aber es dauert zu viel Zeit. Gibt es eine Alternative dazu? oder wenn Sie Feedback darüber haben, wie Sie es weiter verbessern können?Wie kann ich die nächste Nachbarsuche mit Python beschleunigen?
"" "# self.voxels ist ein 3D-numpy Array """
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
Beispiel
"" "Hier ist ein kleines Beispiel mit kleiner Datenmenge: """
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
zur Visualisierung:
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()
Nein w, wenn ich die Dimension des Voxel-Arrays als etwas wie (500,500,500) habe, dann ist die Zeit, die benötigt wird, um die nächste Suche zu berechnen, nicht mehr effizient. Wie kann ich das überwinden? Könnte parallele Berechnung die Zeit reduzieren (ich habe keine Ahnung, ob ich den Code parallelisieren kann, wenn Sie das tun, lassen Sie es mich bitte wissen)?
Ein mögliches fix:
Ich konnte die Rechenzeit erheblich verbessern, indem die n_jobs Zugabe = -1 Parameter in der cKDTree Abfrage.
distances, ndx = tree.query(b, k=1, distance_upper_bound= 5., n_jobs=-1)
I war in der Lage, die Abstände in weniger als eine Stunde für eine Anordnung von (400.100.100) auf einem 13-Core-CPU zu berechnen. Ich habe es mit 1 Prozessor versucht und es dauert ungefähr 18 Stunden, um das gleiche Array zu vervollständigen. Danke an @gsamaras für die Antwort!
Als eine Annahme können Sie Methoden von http://scikit-learn.org/stable/modules/generated/sklearn.neighbors.NearestNeighbors.html#sklearn.neighbors.NearestNeighbors versuchen, aber ich denke, das Problem ist in der Speicherkapazität. (500.500.500) ist wirklich ein riesiges Objekt. –
Hallo @gsamaras, Danke für die Antwort. Ich habe mit dem sklearn Nachbarn Ansatz tr, aber die Zeit der Berechnung scheint nicht viel größeren Einfluss zu haben. Ich warte, wenn jemand anders mit einer anderen Antwort kommen könnte, bevor ich deine Antwort als die letzte akzeptiere. Da deine Antwort viel näher an dem ist, was ich gefragt habe, werde ich deine Antwort akzeptieren. Danke nochmal! –
Hmm, ich sehe @RavirajpurohitPurushottamr, vielen Dank für Ihre Eingabe, viel Glück! – gsamaras