2016-09-11 4 views
1

Ich möchte die 3D-Würfel (3x3x3) aus einem booleschen 3D-Array von (180x180x197) extrahieren. Dies ist vergleichbar mit scipy.ndimage.measurements.label, muss aber eine feste Größe von (3x3x3) haben. Gibt es eine schnelle Möglichkeit, dies zu tun, als für For-Schleifen.numpy Auszug 3d Würfel aus 3D-Array

+0

Letzte ähnlichen Thema: http://stackoverflow.com/questions/39429900/split-a-3d -numpy-array-in-3d-blocks – hpaulj

Antwort

2

In Ihrem speziellen Fall empfehle ich ndhandage.minimum_filter Nehmen wir an, Ihr Array heißt "a". Die folgende:

centers = ndimage.minimum_filter(a, 3, mode="constant") 

enthält nur diejenigen, bei denen das Array solche Schachtel stimmt enthalten Dann sind Sie scipy.ndimage.measurements.label mit der Standard-Struktur verwenden können, um die Boxen zu klassifizieren und vielleicht angeschlossenen Boxs zu identifizieren. Um sie zu lokalisieren können Sie ndimage.measurements.find_objects

bearbeiten verwenden:

Die Art und Weise oben, du bist richtig die Zentren der alle Würfel im Array erhalten. Um es klar zu sagen, ich denke, das ist die Antwort auf Ihre erste Frage. In den Kommentaren stellte sich heraus, dass in der Tat nur nicht überlappende Würfel benötigt werden. Daher muss man die Ausgabe von minimum_filter analysieren, wobei ich mir viele Ansätze vorstellen kann.

Man kann verwenden die nur einen Würfel pro Cluster zu erhalten, folgende:

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) 

Nun tritt das Problem auf, dass Würfel verloren werden, die nicht überlappen, sondern ein Gesicht teilen. Tatsächlich kann man sich ziemlich komplizierte Strukturen von nicht überlappenden, sich teilenden Würfeln vorstellen. Sicherlich gibt es mehrere Lösungen (Sätze von nicht überlappenden Cubes), die für dieses Problem gefunden werden können. Es ist also eine völlig neue Aufgabe, aus den gefundenen Zentren eine Reihe von Würfeln auszuwählen, und ich denke, Sie werden eine finden müssen, die für Sie ideal ist.

Eine Möglichkeit könnte sein, durch alle Lösungen zu durchlaufen und stellen Sie die einzelnen gefundenen Würfel auf 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) 

Ich denke, nur sehr wenige Iterationen notwendig sein wird.

Ich hoffe, das ist das, was Sie suchen

+0

Ich habe das versucht, aber das tut nicht, was ich tun muss. Ich muss die 3x3x3 Würfel aus der Menge der Wahren Werte finden. Und sobald ein Würfel identifiziert ist, können diese Wahr-Werte nicht im nächsten Würfel sein. Und die Würfel müssen separat beschriftet werden. Ich war nicht in der Lage, den Weg dafür zu finden. Danke für die Hilfe/. – ssm

+0

Nun, wenn ich richtig verstehe, tut es fast, was Sie wollen, aber zusätzlich brauchen Sie nicht überlappende Würfel. Was willst du dann bekommen, wenn 2 oder mehr Würfel überlappen? Welcher ist ein echter Würfel und welcher nicht? Das obige gibt Ihnen eine True für jedes Zentrum eines Würfels. Wenn sich Cubes überlappen, ist die maximale Entfernung dieser Zentren dann kleiner als 3. Wenn Sie nicht angeben, was mit überlappenden Cubes zu tun ist, können Sie sie zumindest mit einem uniform_filter identifizieren. – dnalow

+0

Wenn eine Gruppe von Zellen zu einem Würfel gehört, kann sie nicht zu einem anderen Würfel gehören. Sagen Sie, wenn Sie 3x3x5 Trues an einem Ort haben. Ich brauche es, um nur 1 3x3x3 Würfel (kann einer der beiden sein) zu zeigen und den anderen zu verwerfen. – ssm

0

Endlösung mit Hilfe von dnalow

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)