Оптимизация восстановления 3D-поверхности из облака точек

#python #surface #open3d

#python #Поверхность #open3d

Вопрос:

Я новичок в o3d, я бы хотел, чтобы кто-нибудь показал мне на основе моего кода 🙂 Я пытаюсь восстановить поверхность из (нескольких) экспериментальных данных. Я хотел бы иметь как можно больше гибкости / настраиваемости.

Мой код выглядит примерно так:

 import open3d as o3d
sys.path.append('..')

output_path=(r"C:UsersGiammarcoDesktopPYTHON_graphsOUTPUTS\")

poisson_mesh=[]
densities=[]

pcd = o3d.geometry.PointCloud()
pcd.normals = o3d.utility.Vector3dVector(np.zeros((1, 3)))  # invalidate existing normals

#load the point cloud
point_cloud=np.array([x,y,z]).T
cloud = PyntCloud.from_instance("open3d", pcd)
pcd.points = o3d.utility.Vector3dVector(point_cloud)
#resise the scale of the sample
vox_grid = o3d.geometry.VoxelGrid.create_from_point_cloud(pcd, 1.)

#presetn in all approaches of plc
kdtree = cloud.add_structure("kdtree")
testc = cloud.get_neighbors(k=5)
distances = pcd.compute_nearest_neighbor_distance()
avg_dist = np.mean(distances)

#compute the normals
pcd.estimate_normals(); #mandatory
#orient the normals
#Number of nearest neighbours: 5 is the minimum to have a closed surface with scale >= 2
pcd.orient_normals_consistent_tangent_plane(7)

#Poisson algorithm
poisson_mesh, densities = o3d.geometry.TriangleMesh.create_from_point_cloud_poisson(pcd, depth=9, width=0, scale=3.5, linear_fit=False)
bbox = pcd.get_axis_aligned_bounding_box()
p_mesh_crop = poisson_mesh.crop(bbox)

# cleaning
# p_mesh_crop =poisson_mesh.simplify_quadric_decimation(6000)
# p_mesh_crop.remove_unreferenced_vertices
# p_mesh_crop.remove_degenerate_triangles()
# p_mesh_crop.remove_duplicated_triangles()
# p_mesh_crop.remove_duplicated_vertices()
# p_mesh_crop.remove_non_manifold_edges()

#designing the surface colour
#densities are the real density of features
densities = np.asarray(densities)
density_colors = plt.get_cmap('viridis')((dgo - dgo.min()) / (dgo.max() - dgo.min()))
density_colors = density_colors[:, :3]

#works for the plotting in o3d
poisson_mesh.vertex_colors = o3d.utility.Vector3dVector(density_colors)


o3d.io.write_triangle_mesh(output_path "bpa_mesh.ply", dec_mesh);
o3d.io.write_triangle_mesh(output_path "p_mesh_c.ply", poisson_mesh);
# o3d.io.write_triangle_mesh(output_path "p_mesh_c.ply", p_mesh_crop);

# my_lods = lod_mesh_export(p_mesh_crop, [100000,50000,10000,1000,100], ".ply", output_path)
my_lods = lod_mesh_export(poisson_mesh, [100000,50000,10000,1000,100], ".ply", output_path)

# o3d.visualization.draw_geometries([pcd, p_mesh_crop], mesh_show_back_face=True)
# o3d.visualization.draw_geometries([pcd, poisson_mesh],mesh_show_back_face=True)
# o3d.visualization.draw_geometries([pcd, poisson_mesh[100000]],point_show_normal=True)

# tri_mesh_pois.show()#designing the surface colour
#densities are the real density of features
densities = np.asarray(densities)
density_colors = plt.get_cmap('viridis')((dgo - dgo.min()) / (dgo.max() - dgo.min()))
density_colors = density_colors[:, :3]

#works for the plotting in o3d
poisson_mesh.vertex_colors = o3d.utility.Vector3dVector(density_colors)
o3d.io.write_triangle_mesh(output_path "p_mesh_c.ply", poisson_mesh);
my_lods = lod_mesh_export(poisson_mesh, [100000,50000,10000,1000,100], ".ply", output_path)

#SHORTCUTS from keyboard: n = show normals, q = quit, w = mesh
o3d.visualization.draw_geometries([pcd, poisson_mesh],mesh_show_back_face=True)
  

Некоторые результаты:

knn пуассона = 7 размер = 1.5

с помощью нормалей

  1. Меня беспокоит опция create_from_point_cloud_poisson fit model: есть ли способ настроить ее параметры не только depth и size ? Существует ли итеративный процесс, который я должен настроить для лучшего преобразования (например, порог)? Как вы можете видеть, расстояние между расчетной поверхностью и экспериментальной точкой довольно велико.

  2. Правильно ли настроена оценка нормалей? Во втором выводе некоторые направления все еще довольно случайны. Я тоже пробовал этот синтаксис: pcd.estimate_normals(search_param=o3d.geometry.KDTreeSearchParamHybrid(radius=0.05,max_nn=20)); , но он не сходится к замкнутой поверхности, а только к плоскости (см. Ниже)

оценка нормалей

Пожалуйста, дайте мне отзывы о моем коде и предложения о том, как его улучшить.

Спасибо за вашу поддержку!