如何使用 PyMeshLab 将人脸数量减少到保证的特定数量

How to use PyMeshLab to reduce number of faces to a guaranteed specific number

提问人:tommyp 提问时间:1/19/2023 更新时间:3/3/2023 访问量:201

问:

我在 PyMeshLab 中有一个 3D 三角形网格,我想将其抽取到一定数量的面。抽取后的面数无法保证 - 这对我来说是一个问题。我需要特定数量的面孔。

我目前正在使用 simplification_quadric_edge_collapse_decimation,但是不能保证手术后的确切面孔数量 - 因此我经常得到的面孔总数比所需数量小 1。 关于如何解决这个问题有什么好主意,例如通过使用其他过滤器、预/后处理来获得确切的面孔数量 - 保证,或其他东西;

PyMeshLab 抽取

评论

0赞 blunova 1/21/2023
除了 之外,是否要更改其他参数的默认值?target_number_of_faces
0赞 tommyp 1/22/2023
我尝试了默认设置以及大多数其他参数,但没有一致的结果。例如,我可以使用另一种操作对网格进行后处理,该操作可以保证正确数量的面(无需完全重新调节)

答:

1赞 Rockcat 3/3/2023 #1

首先,您需要了解simplification_quadric_edge_collapse_decimation方法的工作原理。它基于 Michael Garland 的 QSlim 算法,该算法基于 Edge Collapse 操作,使用小步执行抽取。

如下图所示,“边折叠”运算符将网格中的三角形数量减少为两部分。这就是您无法在抽取网格中选择确切数量的三角形的原因:有时您“比目标三角形数高一个三角形”,应用运算符将使您“比目标低一个三角形”。

enter image description here

尽管看起来“边缘折叠抽取”将生成一个面数与初始网格具有相同奇偶校验的网格,但这并不总是正确的。当您应用一个“边折叠”(Edge Collapse) 运算符时,如果边是内部的(由两个三角形共享),它将删除两个三角形,但如果边位于网格的边界内,则只会删除一个三角形。这意味着,如果网格具有边界,则可以以与初始网格不同的奇偶校验结束。

我的建议:将网格缩减到目标三角形数量,如果低于所需数量,则向网格添加一个三角形。如果有边界,则可以在边界中选择一个三角形,然后只应用一个中点细分步骤。这应该只影响所选三角形的一个外边,如下图所示:

Increase the number of triangles using midpoint subdivision

这是实现此方法以实现精确抽取的代码:

import pymeshlab as ml
ms = ml.MeshSet()
ms.load_new_mesh('input.ply')
m = ms.current_mesh()
print('input mesh has', m.vertex_number(), 'vertex and', m.face_number(), 'faces')

#Target number of vertex
TARGET=6789

#Reduce to TARGET. Sometimes will fall into TARGET-1
ms.meshing_decimation_quadric_edge_collapse(targetfacenum=TARGET, preservenormal=True)

#Check if we need to increase the number of triangles by one
if ms.current_mesh().face_number() < TARGET:
  #Select the boundary of the mesh
  ms.compute_selection_from_mesh_border()
  if ms.current_mesh().selected_face_number() == 0 : 
      raise("No boundary")
  #Choose one triangle from the boundary
  t=next(i for i,x in enumerate(ms.current_mesh().face_selection_array()) if x )
  #print("Subdivide the boundary triangle", t)
  ms.compute_selection_by_condition_per_face(condselect=f'(fi == {t})')
  ms.meshing_surface_subdivision_midpoint(iterations=1,threshold=ml.AbsoluteValue(0),selected=True)
  
m = ms.current_mesh()
print('output mesh has', m.vertex_number(), 'vertex and', m.face_number(), 'faces')
ms.save_current_mesh('output.ply')

这是毕达哥拉斯网格(342,297 个三角形)的输入和输出,给定需要校正步骤的目标三角形数量 (6789)。

Pythagoras original and decimated to 6789 triangles.

如果某些网格没有边界,则在尝试更改三角形数量的奇偶校验时可能会遇到问题。

评论

0赞 tommyp 3/10/2023
精彩而彻底的回应 - 谢谢@Rockcat。我正在考虑这样做 - 在网格边界上添加一个三角形,但想知道是否有另一种更好的实践方法;不过,我会继续这个。