Suavizado y simplificación de superficies#

Cuando se trabaja con mallas de superficie, es una tarea común simplificar estas mallas para permitir su análisis. También puede ser necesario suavizarlas, por ejemplo, para evitar medir estructuras voxeladas.

import napari_process_points_and_surfaces as nppas
import vedo

Nuestro punto de partida es el branchoide simulado que guardamos en el disco anteriormente en este capítulo.

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

Suavizado de mallas#

Las estructuras circulares que ves en este conjunto de datos resultan del origen de los datos: La superficie fue creada a partir de una imagen binaria. Las líneas corresponden a bordes de vóxeles. Medir el área de la superficie sería engañoso. Por lo tanto, necesitamos suavizar el conjunto de datos antes de hacer mediciones cuantitativas.

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

También podemos modificar qué tan fino se aplica el suavizado.

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

Los parámetros también permiten eliminar la estructura local, en particular el número de iteraciones.

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

También hay más funciones para suavizar superficies, por ejemplo, basadas en mínimos cuadrados móviles.

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

Simplificación de mallas de superficie#

En caso de que una malla de superficie tenga demasiados vértices y caras, su procesamiento puede llevar mucho tiempo. Las mallas de superficie demasiado detalladas pueden no aportar información adicional. Por lo tanto, puede tener sentido simplificar las superficies, por ejemplo, reduciendo a la mitad el número de vértices y caras.

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

Si simplificamos demasiado la superficie, podemos perder información espacial y resolución. El objeto puede entonces no estar representado adecuadamente.

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