Glätten und Vereinfachen von Oberflächen#

Bei der Arbeit mit Oberflächennetzen ist es eine häufige Aufgabe, diese Netze zu vereinfachen, um ihre Analyse zu ermöglichen. Auch das Glätten kann notwendig sein, beispielsweise um die Messung von voxelierten Strukturen zu vermeiden.

import napari_process_points_and_surfaces as nppas
import vedo

Unser Ausgangspunkt ist das simulierte Branchoid, das wir früher in diesem Kapitel auf der Festplatte gespeichert haben.

mesh = vedo.load("../../data/branchoid.ply")
surface = nppas.to_napari_surface_data(mesh)
surface
nppas.SurfaceTuple
origin (z/y/x)[0. 0. 0.]
center of mass(z/y/x)50.000,46.575,42.589
scale(z/y/x)1.000,1.000,1.000
bounds (z/y/x)25.500...74.500
2.500...88.500
2.500...83.500
average size31.277
number of vertices19040
number of faces38076

Glätten von Netzen#

Die kreisförmigen Strukturen, die Sie in diesem Datensatz sehen, resultieren aus dem Ursprung der Daten: Die Oberfläche wurde aus einem Binärbild erstellt. Die Linien entsprechen Voxelkanten. Eine Messung der Oberfläche wäre irreführend. Daher müssen wir den Datensatz glätten, bevor wir quantitative Messungen durchführen.

smoothed_surface = nppas.smooth_surface(surface)
smoothed_surface
nppas.SurfaceTuple
origin (z/y/x)[0. 0. 0.]
center of mass(z/y/x)50.000,46.578,42.588
scale(z/y/x)1.000,1.000,1.000
bounds (z/y/x)25.347...74.653
2.328...88.704
2.334...83.678
average size31.345
number of vertices19040
number of faces38076

Wir können auch anpassen, wie fein die Glättung angewendet wird.

smoothed_surface2 = nppas.smooth_surface(surface, pass_band=0.01)
smoothed_surface2
nppas.SurfaceTuple
origin (z/y/x)[0. 0. 0.]
center of mass(z/y/x)50.000,46.577,42.588
scale(z/y/x)1.000,1.000,1.000
bounds (z/y/x)25.360...74.640
2.296...88.797
2.302...83.693
average size31.349
number of vertices19040
number of faces38076

Die Parameter erlauben auch das Entfernen lokaler Strukturen, insbesondere durch die Anzahl der Iterationen.

smoothed_surface3 = nppas.smooth_surface(surface, number_of_iterations=100,
                                         pass_band=0.00001, 
                                        )
smoothed_surface3
nppas.SurfaceTuple
origin (z/y/x)[0. 0. 0.]
center of mass(z/y/x)50.013,46.548,42.623
scale(z/y/x)1.000,1.000,1.000
bounds (z/y/x)27.575...72.373
6.941...82.192
7.009...79.894
average size29.331
number of vertices19040
number of faces38076

Es gibt auch weitere Funktionen zum Glätten von Oberflächen, z.B. basierend auf Moving Least Squares.

nppas.smooth_surface_moving_least_squares_2d(surface, smoothing_factor=0.2)
 ━━━━━━━━━━━━━━━━━━━━━━ elapsed: 5s (3714.7 it/s)             (3707.5 it/s)         working ...
nppas.SurfaceTuple
origin (z/y/x)[0. 0. 0.]
center of mass(z/y/x)50.000,46.575,42.589
scale(z/y/x)1.000,1.000,1.000
bounds (z/y/x)25.500...74.500
2.500...88.488
2.500...83.500
average size31.218
number of vertices19040
number of faces38076
nppas.smooth_surface_moving_least_squares_2d_radius(surface, smoothing_factor=0.2, radius=3)
 ━━━━━━━━━━━━━━━━━━━━━━ elapsed: 5s (3572.6 it/s)             (3577.5 it/s)         working ...
nppas.SurfaceTuple
origin (z/y/x)[0. 0. 0.]
center of mass(z/y/x)50.000,46.575,42.589
scale(z/y/x)1.000,1.000,1.000
bounds (z/y/x)25.500...74.500
2.500...88.500
2.500...83.500
average size31.211
number of vertices19040
number of faces38076

Vereinfachen von Oberflächennetzen#

Falls ein Oberflächennetz zu viele Vertices und Faces hat, kann die Verarbeitung lange dauern. Zu detaillierte Oberflächennetze bringen möglicherweise auch keine zusätzlichen Informationen. Daher kann es sinnvoll sein, Oberflächen zu vereinfachen, zum Beispiel indem die Anzahl der Vertices und Faces um die Hälfte reduziert wird.

simplified_surface = nppas.decimate_pro(smoothed_surface, fraction=0.5)
simplified_surface
nppas.SurfaceTuple
origin (z/y/x)[0. 0. 0.]
center of mass(z/y/x)50.024,46.096,39.540
scale(z/y/x)1.000,1.000,1.000
bounds (z/y/x)25.347...74.653
2.332...88.704
2.338...83.678
average size32.057
number of vertices9521
number of faces19038

Wenn wir die Oberfläche zu stark vereinfachen, können wir räumliche Informationen und Auflösung verlieren. Das Objekt wird dann möglicherweise nicht mehr angemessen dargestellt.

simplified_surface2 = nppas.decimate_quadric(smoothed_surface, fraction=0.1)
simplified_surface2
nppas.SurfaceTuple
origin (z/y/x)[0. 0. 0.]
center of mass(z/y/x)49.963,47.454,39.244
scale(z/y/x)1.000,1.000,1.000
bounds (z/y/x)25.366...74.634
2.312...88.678
2.318...83.672
average size31.565
number of vertices1905
number of faces3806
simplified_surface2 = nppas.decimate_quadric(smoothed_surface, fraction=0.01)
simplified_surface2
nppas.SurfaceTuple
origin (z/y/x)[0. 0. 0.]
center of mass(z/y/x)50.146,45.715,39.357
scale(z/y/x)1.000,1.000,1.000
bounds (z/y/x)25.440...74.623
2.344...88.258
2.412...83.760
average size31.898
number of vertices192
number of faces380
simplified_surface2 = nppas.decimate_quadric(smoothed_surface, fraction=0.001)
simplified_surface2
nppas.SurfaceTuple
origin (z/y/x)[0. 0. 0.]
center of mass(z/y/x)49.941,45.866,38.671
scale(z/y/x)1.000,1.000,1.000
bounds (z/y/x)25.548...75.905
3.858...93.107
3.380...86.408
average size33.976
number of vertices22
number of faces38