使用Python 构建球体/正方体/多面体/兔子/八面体等点云,Open3D可视化及重建 点云生成8面体点并拟合绘制表面重建结果。(官方示例兔子,8面体,多面体,球体)
- 1. 效果图
- 8面体
- 多面体效果图
- **俩个整8面体效果图**
- 球形/正方体点云
- **兔子效果图**
- 2. 源码
- 2.1 icosahedron.ply
- 2.2 pcd_tn.py
- 参考
点云生成8面体点并拟合绘制表面重建结果。(官方示例兔子,8面体,多面体,球体)
1. 效果图
8面体
原始点云:
多面体效果图
原始点云
俩个整8面体效果图
球形/正方体点云
兔子效果图
2. 源码
2.1 icosahedron.ply
ply
format ascii 1.0
comment VTK generated PLY File
obj_info vtkPolyData points and polygons: vtk4.0
element vertex 12
property float x
property float y
property float z
element face 20
property list uint8 uint32 vertex_indices
end_header
0.0000 -0.0000 -1.0000
0.8912 -0.0000 -0.4536
0.2754 0.8476 -0.4536
-0.7210 0.5238 -0.4536
-0.7210 -0.5238 -0.4536
0.2754 -0.8476 -0.4536
0.7210 0.5238 0.4536
-0.2754 0.8476 0.4536
-0.8912 0.0000 0.4536
-0.2754 -0.8476 0.4536
0.7210 -0.5238 0.4536
0.0000 -0.0000 1.0000
3 0 1 2
3 0 2 3
3 0 3 4
3 0 4 5
3 0 5 1
3 1 2 6
3 1 5 10
3 1 6 10
3 2 6 7
3 2 3 7
3 3 7 8
3 3 4 8
3 4 8 9
3 4 5 9
3 5 9 10
3 6 7 11
3 7 8 11
3 8 9 11
3 9 10 11
3 6 10 11
2.2 pcd_tn.py
# pcd_tn.py
# 构建球体/正方体/多面体/兔子/八面体等点云及可视化,重建
import random
import numpy as np
import open3d as o3d
# 随机种子,以便复现结果
random.seed(123)
# 八面体
def octahedron():
"""Construct an eight-sided polyhedron"""
f = np.sqrt(2.0) / 2.0
verts = np.float32([(0, -1, 0), (-f, 0, f), (f, 0, f), (f, 0, -f), (-f, 0, -f), (0, 1, 0)])
triangles = np.int32([(0, 2, 1), (0, 3, 2), (0, 4, 3), (0, 1, 4), (5, 1, 2), (5, 2, 3), (5, 3, 4), (5, 4, 1)])
val = verts[triangles].tolist()
points = []
for i in val:
print(i,len(points))
for ttt in zip(np.linspace(i[0][0], i[1][0], 15), np.linspace(i[0][1], i[1][1], 15),
np.linspace(i[0][2], i[1][2], 15)):
# print(ttt)
points.append(ttt)
print(len(points))
# for ttt in zip(np.linspace(i[1][0], i[1][0], 15),np.linspace(i[0][1],i[1][1],15),np.linspace(i[0][2],i[1][2],15)):
# # print(ttt)
# points.append(ttt)
# for ttt in zip(np.linspace(i[2][0], i[2][0], 15),np.linspace(i[0][1],i[1][1],15),np.linspace(i[1][2],i[1][2],15)):
# # print(ttt)
# points.append(ttt)
for j in i:
points.append(j)
return points
# 球体
def point_generator(npoints, r):
result = []
# 0 < theta < 2*np.pi
# 0 < phi < np.pi
for i in range(npoints):
theta = random.random() * 2 * np.pi
phi = random.random() * np.pi
x = r * np.cos(theta) * np.sin(phi)
y = r * np.sin(theta) * np.sin(phi)
z = r * np.cos(phi)
result.append([x, y, z])
return result
# 正六面体
def point_generator_square(npoints, r):
result = []
for i in range(npoints // 6):
x = random.random() * 100
y = random.random() * 100
z = 0
result.append([x, y, z])
x = random.random() * 100
z = random.random() * 100
y = 0
result.append([x, y, z])
y = random.random() * 100
z = random.random() * 100
x = 0
result.append([x, y, z])
x = random.random() * 100
y = random.random() * 100
z = 100
result.append([x, y, z])
x = random.random() * 100
z = random.random() * 100
y = 100
result.append([x, y, z])
y = random.random() * 100
z = random.random() * 100
x = 100
result.append([x, y, z])
y = random.random() * 100
z = random.random() * 100
x = random.random() * 100
result.append([x, y, z])
return result
def test_rabbit():
bunny = o3d.data.BunnyMesh()
print(bunny.path)
mesh = o3d.io.read_triangle_mesh(bunny.path)
print(mesh)
mesh.compute_vertex_normals()
pcd = mesh.sample_points_poisson_disk(750)
print(pcd)
o3d.visualization.draw_geometries([pcd], width=800, height=600, left=50,
top=50,
point_show_normal=True, mesh_show_wireframe=False,
mesh_show_back_face=False)
alpha = 0.03
print(f"alpha={alpha:.3f}")
mesh = o3d.geometry.TriangleMesh.create_from_point_cloud_alpha_shape(pcd, alpha)
print(mesh)
mesh.compute_vertex_normals()
o3d.visualization.draw_geometries([mesh], width=800, height=600, left=50,
top=50,
point_show_normal=True, mesh_show_wireframe=False,
mesh_show_back_face=True)
tetra_mesh, pt_map = o3d.geometry.TetraMesh.create_from_point_cloud(pcd)
for alpha in np.logspace(np.log10(0.5), np.log10(0.01), num=4):
print(f"alpha={alpha:.3f}")
mesh = o3d.geometry.TriangleMesh.create_from_point_cloud_alpha_shape(
pcd, alpha, tetra_mesh, pt_map)
mesh.compute_vertex_normals()
o3d.visualization.draw_geometries([mesh], "Open3D origin points " + str(alpha), width=800, height=600, left=50,
top=50,
point_show_normal=True, mesh_show_wireframe=False,
mesh_show_back_face=True)
bunny = o3d.data.BunnyMesh()
gt_mesh = o3d.io.read_triangle_mesh(bunny.path)
gt_mesh.compute_vertex_normals()
pcd = gt_mesh.sample_points_poisson_disk(3000)
o3d.visualization.draw_geometries([pcd], width=800, height=600, left=50,
top=50,
point_show_normal=True, mesh_show_wireframe=False,
mesh_show_back_face=False)
radii = [0.005, 0.01, 0.02, 0.04]
rec_mesh = o3d.geometry.TriangleMesh.create_from_point_cloud_ball_pivoting(
pcd, o3d.utility.DoubleVector(radii))
o3d.visualization.draw_geometries([pcd, rec_mesh], width=800, height=600, left=50,
top=50,
point_show_normal=True, mesh_show_wireframe=False,
mesh_show_back_face=False)
def test_rabbit2(path):
print(path)
mesh = o3d.io.read_triangle_mesh(path)
mesh.compute_vertex_normals()
pcd = mesh.sample_points_poisson_disk(750)
print(pcd)
o3d.visualization.draw_geometries([pcd], width=800, height=600, left=50,
top=50,
point_show_normal=True, mesh_show_wireframe=False,
mesh_show_back_face=False)
alpha = 0.03
print(f"alpha={alpha:.3f}")
mesh = o3d.geometry.TriangleMesh.create_from_point_cloud_alpha_shape(pcd, alpha)
print(mesh)
mesh.compute_vertex_normals()
o3d.visualization.draw_geometries([mesh], width=800, height=600, left=50,
top=50,
point_show_normal=True, mesh_show_wireframe=False,
mesh_show_back_face=True)
tetra_mesh, pt_map = o3d.geometry.TetraMesh.create_from_point_cloud(pcd)
for alpha in np.logspace(np.log10(0.5), np.log10(0.01), num=8):
print(f"alpha={alpha:.3f}")
mesh = o3d.geometry.TriangleMesh.create_from_point_cloud_alpha_shape(
pcd, alpha, tetra_mesh, pt_map)
mesh.compute_vertex_normals()
o3d.visualization.draw_geometries([mesh], "Open3D origin points " + str(alpha), width=800, height=600, left=50,
top=50,
point_show_normal=True, mesh_show_wireframe=False,
mesh_show_back_face=True)
gt_mesh = o3d.io.read_triangle_mesh(path)
gt_mesh.compute_vertex_normals()
pcd = gt_mesh.sample_points_poisson_disk(3000)
o3d.visualization.draw_geometries([pcd], width=800, height=600, left=50,
top=50,
point_show_normal=True, mesh_show_wireframe=False,
mesh_show_back_face=False)
radii = [0.005, 0.01, 0.02, 0.04]
rec_mesh = o3d.geometry.TriangleMesh.create_from_point_cloud_ball_pivoting(
pcd, o3d.utility.DoubleVector(radii))
o3d.visualization.draw_geometries([pcd, rec_mesh], width=800, height=600, left=50,
top=50,
point_show_normal=True, mesh_show_wireframe=False,
mesh_show_back_face=False)
def test_demo(path, pcd):
o3d.visualization.draw_geometries([pcd], "Open3D origin points", width=800, height=600, left=50,
top=50,
point_show_normal=True, mesh_show_wireframe=False,
mesh_show_back_face=True)
print(path)
mesh = o3d.io.read_triangle_mesh(path)
print(mesh)
mesh.compute_vertex_normals()
# pcd = mesh.sample_points_poisson_disk(750)
# print(pcd)
# o3d.visualization.draw_geometries([pcd], width=800, height=600, left=50,
# top=50,
# point_show_normal=True, mesh_show_wireframe=False,
# mesh_show_back_face=False)
alpha = 0.03
print(f"alpha={alpha:.3f}")
mesh = o3d.geometry.TriangleMesh.create_from_point_cloud_alpha_shape(pcd, alpha)
print(mesh)
mesh.compute_vertex_normals()
o3d.visualization.draw_geometries([mesh], width=800, height=600, left=50,
top=50,
point_show_normal=True, mesh_show_wireframe=False,
mesh_show_back_face=True)
tetra_mesh, pt_map = o3d.geometry.TetraMesh.create_from_point_cloud(pcd)
for alpha in np.logspace(np.log10(0.5), np.log10(0.01), num=4):
print(f"alpha={alpha:.3f}")
mesh = o3d.geometry.TriangleMesh.create_from_point_cloud_alpha_shape(
pcd, alpha, tetra_mesh, pt_map)
mesh.compute_vertex_normals()
o3d.visualization.draw_geometries([mesh, pcd], "Open3D origin points " + str(alpha), width=800, height=600,
left=50,
top=50,
point_show_normal=True, mesh_show_wireframe=False,
mesh_show_back_face=True)
def get_pcd(path, type="ball"):
npoints = 5000
r = np.sqrt(3)
if type == "ball":
points = point_generator(npoints, r)
elif type == "square":
points = point_generator_square(npoints, r)
else:
points = octahedron()
val = np.array(points)
# 计算点云均值点,并插入到原点云点的第一个点
avg_point = np.mean(val, axis=0) # axis=0,计算每一列的均值
origin_points = np.row_stack((avg_point, val))
# 构造点云数据
pcd = o3d.geometry.PointCloud()
points = o3d.utility.Vector3dVector(origin_points)
pcd.points = points
print(pcd)
o3d.io.write_point_cloud(path, pcd)
return pcd
path = "D:/study/python-scripts/p230531/input/test_ball.pcd"
ball_pcd = get_pcd(path, type="ball")
o3d.visualization.draw_geometries([ball_pcd], "Open3D origin points", width=800, height=600, left=50,
top=50,
point_show_normal=True, mesh_show_wireframe=False,
mesh_show_back_face=True)
path = "D:/study/python-scripts/p230531/input/test_square.pcd"
test_demo(path, get_pcd(path, type="square"))
path = "D:/study/python-scripts/p230531/input/test_eight.pcd"
test_demo(path, get_pcd(path, type="eight"))
test_rabbit2("D:/study/python-scripts/p230531/input/icosahedron.ply")
test_rabbit()
参考
- http://www.open3d.org/docs/release/tutorial/geometry/surface_reconstruction.html