I have a batch of triangle meshes and each one has different vertices and faces. I want to reduce the vertex numbers of all the meshes to the same number, 10000.
I know I can use simplification_quadric_edge_collapse_decimation to reduce the face number which means the vertex number will be reduced accordingly. But the problem is that I have to use the method several times in order to get the vertex number exactly down to 10000.
Therefore, I'm wondering if there is another way to reduce the vertex number to 10000 directly?
Meshlab, and to my knowledge any other libraries able to simplify, use the face number as the parameter to guide simplification process.
The good news are that both values are related by the Euler characteristic of the mesh, which roughly says that the number of vertex is half the number of faces for a surface without holes. Decimating your mesh to 20000 faces will produce a mesh of about 10000 vertex, but you can also fall under 9999 easily. As you have the advantage of being programming in python, you can design a process to slowly converge to the desired number of vertex.
The idea is to simplify your mesh to a face number slightly above of 20000, and then slowly refine your solution until you get exactly 10000 vertex. I propose you to reduce the number of faces in each step using the excess of vertex on current step (vertex_number - 10000).
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=10000
#Estimate number of faces to have 100+10000 vertex using Euler
numFaces = 100 + 2*TARGET
#Simplify the mesh. Only first simplification will be agressive
while (ms.current_mesh().vertex_number() > TARGET):
ms.apply_filter('simplification_quadric_edge_collapse_decimation', targetfacenum=numFaces, preservenormal=True)
print("Decimated to", numFaces, "faces mesh has", ms.current_mesh().vertex_number(), "vertex")
#Refine our estimation to slowly converge to TARGET vertex number
numFaces = numFaces - (ms.current_mesh().vertex_number() - TARGET)
m = ms.current_mesh()
print('output mesh has', m.vertex_number(), 'vertex and', m.face_number(), 'faces')
ms.save_current_mesh('output.ply')
Please, note that:
numFaces = numFaces - int(1.5*(ms.current_mesh().vertex_number() - 10000))
, but this increases the chances of ending under 9999 vertex and execution time won't be affected much.