Как использовать PyMeshLab для уменьшения числа вершин до определенного числа
У меня есть партия треугольных сеток, каждая из которых имеет разные вершины и грани. Я хочу уменьшить количество вершин всех сеток до одного и того же числа, 10000.
Я знаю, что могу использовать simpleification_quadric_edge_collapse_decimation, чтобы уменьшить количество граней, что означает, что количество вершин будет соответственно уменьшено. Но проблема в том, что мне приходится использовать этот метод несколько раз, чтобы получить номер вершины ровно до 10000.
Поэтому мне интересно, есть ли другой способ напрямую уменьшить число вершин до 10000?
1 ответ
Meshlab и, насколько мне известно, любые другие библиотеки, способные упростить, используют номер грани в качестве параметра для руководства процессом упрощения.
Хорошая новость заключается в том, что оба значения связаны эйлеровой характеристикой сетки, которая примерно говорит о том, что количество вершин составляет половину количества граней для поверхности без отверстий. Урезание вашей сетки до 20000 граней даст сетку с примерно 10000 вершинами, но вы также можете легко упасть ниже 9999. Поскольку у вас есть преимущество программирования на Python, вы можете спроектировать процесс, сходящийся к нескольким вершинам.
Итак, идея состоит в том, чтобы упростить вашу сетку до числа граней немного выше 20000, а затем медленно улучшать ваше решение, пока вы не получите 10000 вершин. Предлагаю уменьшать количество граней на каждом шаге за счет превышения вершины на текущем шаге (вершина - 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')
Обратите внимание:
- Иногда вы просто не можете сократить ровно до 10000 вершин, а закончите на 9999 вершинах.
- С помощью этой формулы каждый шаг (после первого) будет удалять примерно половину вершин, превышающих 10000, давая «мягкую посадку» в желаемое количество вершин. Типичное выполнение должно уменьшиться примерно до 10050 вершин, затем до 10025, 10012, 10006, 10003, 10001 и, наконец, до 10000 вершин. Конечное количество граней зависит от указанной характеристики Эйлера входной модели.
- Только первый шаг упрощения потребует значительного времени выполнения (в зависимости от количества треугольников во входной сетке), а следующие шаги упрощения будут очень быстрыми.
- Если вы все еще хотите ускорить метод, вы можете сделать
numFaces = numFaces - int(1.5*(ms.current_mesh().vertex_number() - 10000))
, но это увеличивает шансы на то, что вершина будет меньше 9999, и время выполнения не сильно изменится. - Этот метод должен работать с любым алгоритмом прореживания, основанным на гранях, он не является исключительным для сжатия квадратичных граней.