Python中的网格简化

4
我有一个包含2百万个三角形的高分辨率三角网格。我想将三角形和顶点数量各减少到约10000个左右,同时尽可能地保留其整体形状。
我知道可以使用Matlab中的reducepatch完成这个任务。另一个选择是qslim包。VTK中也有可缩减功能,并且具有Python接口,因此在Python中也可以实现。Meshlab可能也可以在Python上使用(?)。
如何在Python中进行这种网格缩减?如果有示例将会非常感激。

2
也许可以用这个例子?它不是Python,但很容易翻译。http://www.vtk.org/Wiki/VTK/Examples/Cxx/Meshes/Decimation - MrPedru22
是的,我看到了,但对于我来说翻译并不容易,因为我只是一个初学者。任何帮助都将不胜感激。 - AnandJ
VTK Python版本的最近更新包括:https://lorensen.github.io/VTKExamples/site/Python/VisualizationAlgorithms/DecimateFran/ - AnandJ
4个回答

5

以下是一个最简Python原型,它是从其c++等效vtk示例( http://www.vtk.org/Wiki/VTK/Examples/Cxx/Meshes/Decimation )翻译而来,正如 MrPedru22 所建议的那样。

from vtk import (vtkSphereSource, vtkPolyData, vtkDecimatePro)


def decimation():
    sphereS = vtkSphereSource()
    sphereS.Update()

    inputPoly = vtkPolyData()
    inputPoly.ShallowCopy(sphereS.GetOutput())

    print("Before decimation\n"
          "-----------------\n"
          "There are " + str(inputPoly.GetNumberOfPoints()) + "points.\n"
          "There are " + str(inputPoly.GetNumberOfPolys()) + "polygons.\n")

    decimate = vtkDecimatePro()
    decimate.SetInputData(inputPoly)
    decimate.SetTargetReduction(.10)
    decimate.Update()

    decimatedPoly = vtkPolyData()
    decimatedPoly.ShallowCopy(decimate.GetOutput())

    print("After decimation \n"
          "-----------------\n"
          "There are " + str(decimatedPoly.GetNumberOfPoints()) + "points.\n"
          "There are " + str(decimatedPoly.GetNumberOfPolys()) + "polygons.\n")


if __name__ == "__main__":
    decimation()

请注意:原始多边形数据中的点必须是唯一的。如果在 polydata.GetPoints() 中存在重复的点,则新网格中会出现间隙。vtkSTLReader 默认情况下会清除重复项,而 vtkXXXSource 设计为无重复项。但是,如果您从头开始创建了此多边形数据或使用非 VTK 读取器读取了网格,则可能需要首先使用 vtkCleanPolyData 进行清理。 - pullmyteeth

4
我建议您使用vtkQuadricDecimation,输出模型的质量在视觉上比使用vtkDecimatePro(未正确设置)更好。
decimate = vtkQuadricDecimation()
decimate.SetInputData(inputPoly)
decimate.SetTargetReduction(0.9)

在保存STL文件时,最重要的事情之一是使用二进制表示法:

stlWriter = vtkSTLWriter()
stlWriter.SetFileName(filename)
stlWriter.SetFileTypeToBinary()
stlWriter.SetInputConnection(decimate.GetOutputPort())
stlWriter.Write()

1

另一个选择是应用开源库MeshLib,它可以从C++和Python代码中调用(在这里通过pip安装)。

减少代码将如下所示:

import meshlib.mrmeshpy as mr

# load high-resolution mesh:
mesh = mr.loadMesh(mr.Path("busto.stl"))

# decimate it with max possible deviation 0.5:
settings = mr.DecimateSettings()
settings.maxError = 0.5
result = mr.decimateMesh(mesh, settings)
print(result.facesDeleted)
# 708298
print(result.vertsDeleted)
# 354149

# save low-resolution mesh:
mr.saveMesh(mesh, mr.Path("simplified-busto.stl"))

从视觉上看,两个网格如下所示: 输入图像描述


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接