平滑和简化表面#

在处理表面网格时,简化这些网格以便进行分析是一项常见任务。同时,平滑处理也可能是必要的,例如为了避免测量体素化结构。

import napari_process_points_and_surfaces as nppas
import vedo

我们的起点是之前在本章中保存到磁盘的模拟分支体。

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

平滑网格#

你在这个数据集中看到的圆形结构源于数据的起源:表面是由二值图像创建的。这些线对应于体素边缘。直接测量表面积会产生误导。因此,在进行定量测量之前,我们需要对数据集进行平滑处理。

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

我们还可以修改平滑的精细程度。

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

这些参数还允许移除局部结构,特别是迭代次数。

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

还有其他用于平滑表面的函数,例如基于移动最小二乘法的方法。

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

简化表面网格#

如果表面网格的顶点和面太多,处理它可能需要很长时间。过于详细的表面网格可能也不会带来额外的信息。因此,简化表面可能是有意义的,例如通过将顶点和面的数量减少一半。

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

如果我们过度简化表面,我们可能会失去空间信息和分辨率。然后对象可能不再被适当地表示。

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